重看APUE
最近在折腾一些东西的时候,发现自己的操作系统知识很可怜,于是打算抽点时间学习APUE。其实与其说是重看,和第一次看也没有太多区别,之前上过一次选修但是很可惜当时没有心境沉下来上课,都做项目去了。现在我很想从头到尾认真的看一遍,虽然目前是做到了,但是以后可能时间吃紧,只能挑着看了。
最好的学习方法当然是看与写结合,所以我第一个例程,我看懂原理之后就会尝试自己“写”一遍,实际情况看比你”自以为看懂”地浏览过去效果要好。
进程
这一部分内容是我遇到的第一个觉得比较有意思的程序,今天就写这个吧,下面是一个简单shell的程序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include "apue.h" int main(void){ char buff[MAXLINE]; pid_t pid; int status; printf("%%"); //打印提示符,两个%% while(fgets(buff,MAXLINE,stdin)!=NULL){ //遇到 EOF会返回NULL,所以可以ctrl+D退出这个shell if( (pid = fork()) <0 ){ //尝试fork,返回负则表示失败,如果成功则会产生父进程的copy err_sys("failed to fork"); }else if(pid == 0){ //fork对子进程返回0,以下进入子进程 buff[strlen(buff)-1]=0; //细节,将回车替换为0 execlp(buff, buff, (char *) 0); //execlp会加载指定程序,并覆盖当前进程数据(也就是说没以下两条指令的事了) err_ret("could not exec %s",buff); //如果进入到这里,则说明加载程序失败了(数据没被erase) exit(127); } //return to the main process, 既然是开启了新进程,自然会立刻返回主进程,我们要设置等待 pid = waitpid(pid, &status , 0); //这个status是子进程的返回状态,这时并没有检查该值 if(pid < 0){ err_sys("wait pid error"); } printf ("%%"); } }
|
运行效果
1 2 3 4 5 6 7 8
| chen@vaio:/data/apue.2e/chen$ ./a.out %ls a.out apue.h error.c mycat.c mycatstdio.c myls.c mysh.c pid.c %pwd /data/apue.2e/chen %date 2015年 04月 17日 星期五 02:08:15 CST %
|
总结
这个程序有两个比较有意思的地方:
- fork一次调用两次返回。以命令执行成功为例,第一个else中返回0给子进程,waitpid时父进程使用的是另一返回值,即子进程ID。
- execlp会加载指定程序并覆盖当前程序栈,所以可以看到execlp之后并没有判断条件就直接可以报错了