apue- chapter 1 UNIX基础知识
1.C++实现ls命令
- #include<dirent.h>
- #include<stdlib.h>
- #include<iostream>
- #include "apue.h"
- using namespace std;
- int main(int argc,char * argv[]){
- DIR *d
- struct dirent *dirp;
- if(argc!=2){
- cout<<"usage: ls directory_name"<<endl;
- exit(-1);
- }
- if((dp=opendir(argv[1]))==NULL){
- cout<<"can't open "<<argv[1]<<endl;
- }
- //循环读取目录项
- while((dirp=readdir(dp))!=NULL){
- //输出文件名称
- cout<<dirp->d_name<<endl;
- }
- closedir(dp);
- exit(0);
- }
opendir函数返回指向DIR结构的指针,我们将该指针传送给readdir函数。在循环中调用 readdir来读取每个目录项。该函数返回指向dirent结构的指针,而当目录中没有目录项可读时返回空指针。然后在循环中输出从dirent结构中 取出的每个目录项的名称。
2.C++ 实现从输出从标准输入中读到的内容
- #include "apue.h"
- #include<iostream>
- using namespace std;
- #define BUFFSIZE 4096
- int main(){
- int n;
- //缓冲
- char buf[BUFFSIZE];
- //从标准输入中读取,缓冲区大小为BUFFSIZE,缓冲区对应buf
- while((n=read(STDIN_FILENO,buf,BUFFSIZE))>0){
- //向标准输出输出buf中的内容
- if(write(STDOUT_FILENO,buf,n)!=n)
- cout<<"wirte error"<<endl;
- }
- //读取标准输入出错
- if(n<0)
- cout<<"read error"<<endl;
- exit(0);
- }
运行截图:
3.使用标准I/O实现例2中的内容
标准I/O函数为那些不带缓冲的I/O函数提供了一个带缓冲的接口。使用标准I/O函数无需担心如何选取最佳的缓冲区大小。
以下用getc函数与putc函数实现例2中的功能。
- #include "apue.h"
- #include <iostream>
- using namespace std;
- int main(){
- int c;
- while((c=getc(stdin))!=EOF){
- if(putc(c,stdout)==EOF)
- cout<<"output error"<<endl;
- }
- if(ferror(stdin))
- cout<<"input error"<<endl;
- return 0;
- }
4.输出进程ID
UNIX确保每个进程都有唯一的数字标识符,成为进程ID。进程ID是一个非负整数。
下面是一个输出本程序进程ID的 程序代码。
- #include "apue.h"
- #include <iostream>
- using namespace std;
- int main(){
- cout<<"hello world from process ID"<<getpid()<<endl;
- return 0;
- }
分别运行两次,输出如下:
hello world from process ID18357
hello world from process ID18385
5.开辟新进程执行输入的命令
利用C++对标准输入 输入的命令开辟新的进程加以执行。
- #include "apue.h"
- #include <sys/wait.h>
- #include <iostream>
- using namespace std;
- int main(){
- char buf[MAXLINE]; //MAXLINE->4096
- pid_t pid;
- int status;
- cout<<"%% ";/* print prompt (printf requires %% to print %)*/
- while(fgets(buf,MAXLINE,stdin)!=NULL){
- //fets函数返回的每一行都以换行符结束,后面紧随一个'\0',需要将换行符号替换为'\0'
- if(buf[strlen(buf)-1]=='\n')//最后一个字符是换行符
- buf[strlen(buf)-1]='\0';//将其替换为结束符号
- //调用fork()创建新进程,fork对父进程返回子进程的ID,对子进程返回0.fork调用一次,在父进程和子进程中各调用一次
- if((pid=fork())<0){
- cout<<"fork error"<<endl;
- }else if(pid==0){//成功创建子进程
- //在子进程中执行buf对应的命令,
- execlp(buf,buf,(char *)0);
- cout<<"could't execute: "<<buf<<endl;
- exit(127);
- }
- //父进程等待子进程结束
- //waitpid()函数返回子进程的终止状态,保存在status中
- /* parent */
- if((pid=waitpid(pid,&status,0))<0)
- cout<<"wait pid error!"<<endl;
- cout<<"%% ";
- }
- return 0;
- }
执行过程:
- %% ls
- b CMakeFiles hello_world Makefile
- CMakeCache.txt cmake_install.cmake hello_world.cbp
- %% date
- 2016年 03月 20日 星期日 23:01:21 CST
上述程序的重点是函数fork以及函数waitpid。fork创建一个新进程。fork对父进程返回子进程的进程ID(非负整数),对子进程返回0。fork调用一次,对父进程和子进程各返回一次。
父进程等待子进程终止是通过waitpid实现的,其参数指定要等待的进程(pid指定),返回子进程的终止状态(status变量)。
6.出错处理
当Unix系统函数出错的时候,通常会返回一个负值,而且整型变量errno通常被设置为具有特定信息的值。
文件<errno.h>定义了errno以及可以赋予它的各种变量,这些变量都以E开头。
C标准定义了两个函数,用于打印出错的信息。
- #include<string.h>
- char *strerror(int errnum)
- //将errnum(errno)映射为一个出错的消息字符串,并且返回这个字符串的指针
- #include<stdio.h>
- void perror(const char * msg)
- //基于当前的errno值,在标准错误上产生一条出错的信息,然后返回。
以下程序是 使用上述两个函数的案例。
- #include<iostream>
- #include<errno.h>
- #include<stdio.h>
- #include <string.h>
- using namespace std;
- int main(int argc,char*argv[]){
- //将EACCES映射为一个出错消息字符串
- fprintf(stderr,"EACCES: %s\n",strerror(EACCES));
- errno=ENOENT;
- //基于当前errno的值,在标准错误上产生一条出错信息
- perror(argv[]);
- }
7.用户id和组id
用户id用于标识不同的用户,root用户的用户id为0.组将同属一个项目或者部门的用户集合在一起,他们一般具有相同的权限,可以访问组权限限定的文件。
以下程序用户获取当前用户的用户id以及组id。
- #include<iostream>
- #include "apue.h"
- using namespace std;
- int main(int argc,char*argv[]){
- //输出用户id和组id
- cout<<"uid="<<getuid()<<",gid= "<<getgid()<<endl;
- }
8. 信号
信号用于通知进程发生了某种情况,例如某一进程执行执行除法操作,其除数为0,则将名为SIGFPE(浮点异常)的信号发送给该进程。进程有以下3种处理信号的方式。
1.忽略信号。2.按系统默认方式处理。3.提供一个函数,信号发生的时候调用该函数,这被称为捕捉该信号。通过自己定义的程序,我们就知道什么时候产生了信号,并按照期望的方式进行处理。
实例:捕捉中断键发出的信号。
- #include<iostream>
- #include "apue.h"
- #include <sys/wait.h>
- using namespace std;
- //用于捕捉信号的函数
- static void sig_int(int signo){//信号处理函数,输出Interrupt
- cout<<"Interrupt "<<endl;
- }
- int main(){
- char buf[MAXLINE];
- pid_t pid;
- int status;
- if(signal(SIGINT,sig_int)==SIG_ERR)//绑定信号
- cout<<"signal error"<<endl;
- cout<<"%% ";
- while(fgets(buf,MAXLINE,stdin)!=NULL){
- if(buf[strlen(buf)-]=='\n')
- buf[strlen(buf)-]='\0';
- if((pid=fork())<){
- cout<<"fork error"<<endl;
- }else if(pid==){
- execlp(buf,buf,(char *));
- cout<<"could't execute :"<<buf<<endl;
- exit(-);
- }
- if((pid=waitpid(pid,&status,))<)
- cout<<"wait pid error"<<endl;
- cout<<"%% ";
- }
- return ;
- }
运行截图:
apue- chapter 1 UNIX基础知识的更多相关文章
- 《UNIX环境高级编程》(APUE) 笔记第一章 - UNIX基础知识
1 - UNIX基础知识 Github 地址 1. 操作系统 可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境.通常将这种软件称为 内核 (kernel) .( Linux 是 GN ...
- UNIX环境高级编程--第一章 UNIX基础知识
第一章 UNIX基础知识 1.2 UNIX体系结构 从严格意义上说,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境.我们将这种软件称为内核(kernel),因为 它相对较小,且 ...
- apue学习笔记(第一章UNIX基础知识)
总所周知,UNIX环境高级编程是一本很经典的书,之前我粗略的看了一遍,感觉理解得不够深入. 听说写博客可以提高自己的水平,因此趁着这个机会我想把它重新看一遍,并把每一章的笔记写在博客里面. 我学习的时 ...
- APUE(1)----UNIX基础知识
一.UNIX体系结构 所有操作系统都为他们所运行的程序提供服务,典型的服务包括:执行新程序.打开文件.读文件.分配存储区等.严格意义上来说,操作系统可以定义为一种软件,它控制计算机硬件资源,提供程序运 ...
- APUE 学习笔记(一) Unix基础知识
1. Unix 体系结构 内核的接口被称为系统调用 公用函数库构建在系统调用接口之上 应用软件既可以调用公用函数库,也可以直接进行系统调用 2. 文件和目录 目录操作函数:opendir--- ...
- 第一章:UNIX基础知识
本章内容主要是为了学习UNIX的基本知识和一些最基本的系统函数. 学习的关键就是跟随者书本敲代码.本节遇到的第一个问题就死本书的apue.h这个文件:一开始没有注意这个文件,盲目的去百度,一番百度之后 ...
- UNIX基础知识之程序和进程
一.程序 程序(program)是存放在磁盘上.处于某个目录中的一个可执行文件.使用6个exec函数中的一个由内核将程序读入存储器,并使其执行. 二.进程和进程ID 程序的执行实例被称为进程(proc ...
- 《UNIX环境高级编程》笔记——1.UNIX基础知识
这一章节侧重一些基本概念和书中用到的一些名词. 一.引言 所有的操作都提供服务,典型的服务包括:执行新程序.打开文件.读写文件.分配存储区以及获得当前时间等. 二.UNIX体系结构 其实linux常见 ...
- UNIX,基础知识,文件IO,文件和目录
2015.1.27星期二,早晨阴天,中午下雪了今天上午老师不上课,程序语句,记一下:main(void){ int c; while((c = getc(stdin)) != EOF) if(putc ...
- UNIX基础知识之时间值
本篇博文内容摘自<UNIX环境高级编程>(第二版),仅作个人学习记录所用.关于本书可参考:http://www.apuebook.com/. 长期以来,UNIX系统一直使用两种不同的时间值 ...
随机推荐
- Android Paint画笔及Color .
引自:http://blog.csdn.net/q445697127/article/details/7736926 Paint paint = new Paint(); // 设置paint为无锯齿 ...
- 8数码,欺我太甚!<bfs+康拓展开>
不多述,直接上代码,至于康拓展开,以前的文章里有 #include<iostream> #include<cstdio> #include<queue> using ...
- brbustoj 1818 石子合并问题--直线版
比较经典且基础的区间dp,转移方程为 dp_max[i][j] = max(dp_max[i][j],dp_max[i][k] + dp_max[k+1][j] + sum[j]-sum[i-1]); ...
- 关于struts2的web.xml配置
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "- ...
- mark一篇文章--用nodejs搭建一个本地反向代理环境
调试线上代码的时候,我们经常遇到的一个问题就是 本地一套环境,线上一套环境,本地没有的文件用线上的这种需求.我简单来说下使用nodejs如何做到. 先说下不用nodejs我们怎么做,工具比如fiddl ...
- Size Balanced Tree(SBT) 模板
首先是从二叉搜索树开始,一棵二叉搜索树的定义是: 1.这是一棵二叉树: 2.令x为二叉树中某个结点上表示的值,那么其左子树上所有结点的值都要不大于x,其右子树上所有结点的值都要不小于x. 由二叉搜索树 ...
- 只有mdf 没有 日志 恢复数据库
1.先建一个与你要恢复的数据库名称一样的数据库.2.停止sql server,把你的数据库替换这个数据库.3.重启sql server,把数据库设置为紧急状态. sp_configure 'allo ...
- json转义字符串
json前台写数据 @RequestMapping("/addUserJson") public void addUserJson(User user,HttpServletReq ...
- IGeoFeatureLayer
Members All Properties Methods Inherited Non-inherited Description AnnotationProperties Annotation ...
- Codeforces#373 Div2
Ranting重新回到浅蓝的一场比赛 Problem A 题意:月亮的大小是按照这样的顺序排列的0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ...