1. 学习进程创建, 等待, 终止. 使用代码实现.
(1)进程创建
fork:在已经存在的进程中创建一个新的进程,新进程为子进程,原来的进程为父进程
--子进程返回的值为0,父进程返回的值为子进程的pid
运行结果为
vfork:也是用来创建子进程的
运行结果与上边相同
-不拷贝内存空间,和父进程共享地址空间(定义变量之后,值相同),--并且能保证子进程先运行,子进程先运行之后父进程才开始运行
-- 必须调用exit或者exec系列函数
否则运行结果如下图所示:
--任何一个系统上实现的vfrok或多或少,不要使用
(2)进程等待
wait:代表父进程一直阻塞,直到子进程退出,回收掉僵尸,然后wait返回到父进程中。
--如左图所示为父进程,创建了子进程之后转到右图,运行子进程代码,而父进程处于阻塞的状态,子进程执行完之后退出,父进程的wait回收掉僵尸进程,然后继续进行父进程。
2. 编写自主shell.
在编写shell时的基本步骤为:
(1)获取命令行
(2)解析命令行
(3)创建一个子进程
(4)替换子进程
(5)父进程等待子进程退出
(1)在linux下使用system需要谨慎,标准I/O函数库提供了popen函数,它启动另外一个进程去执行一个shell命令行。
这里我们称调用popen的进程为父进程,由popen启动的进程称为子进程。
popen函数还创建一个管道用于父子进程间通信。父进程要么从管道读信息,要么向管道写信息,至于是读还是写取决于父进程调用popen时传递的参数。下在给出popen、pclose的定义:
下面通过例子看下popen的使用:
假如我们想取得当前目录下的文件个数,在shell下我们可以使用:
在程序中使用popen:
上面popen只捕获了command的标准输出,如果command执行失败,子进程会把错误信息打印到标准错误输出,父进程就无法获取。比如,command命令为“ls nofile.txt” ,事实上我们根本没有nofile.txt这个文件,这时shell会输出“ls: nofile.txt: No such file or directory”。这个输出是在标准错误输出上的。通过上面的程序并无法获取。
(2)system函数
system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命>令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略。 返回值 =-1:出现错误 =0:调用成功但是没有出现子进程 >0:成功退出的子进程的id 如果system()在调用/bin/sh时失败则返回127,其他失败原因返回-1。若参数string为空指针(NULL),则返回非零值>。如果system()调用成功则最后会返回执行shell命令后的返回值,但是此返回值也有可能为 system()调用/bin/sh失败所返回的127,因此最好能再检查errno 来确认执行成功。
(3)所以system和popen的最大区别:system就是执行shell命令最后返回是否执行成功,popen执行命令并且通过管道和shell命令进行通信。