fork函数调用完成后,将生成新的进程,原来的调用进程称为父进程,新生成的进程成为子进程,
最关键的是调用一次竟然有两个返回值,这是原来C语言函数所没有见过的,在父进程里面,返回
值是子进程的ID号,在子进程里面返回值是0,出错返回-1.
fork函数调用成功后,产生的子进程继承了父进程的大部分属性,主要包括以下几点:
1.进程的实际用户ID,实际用户组ID,有效用户ID,有效用户组ID。
2.进程ID,会话ID,控制终端。
3.当前的工作目录和根目录。
4.文件创建掩码,UMASK。
5.环境变量。
不能继承的属性:
1.进程号
2.子进程用户时间和系统时间,这两个时间初始化为0.
3.子进程的信号处理函数指针组置为空。原来的父进程的信号处理函数都失效。
4.父进程的记录锁。
使用注意事项:
父进程已打开的文件描述符号可以在子进程直接使用。没调用一次fork描述符的引用计数加1。关闭描述符
时候多次关闭,直至为0.
子进程拷贝了父进程的数据段,包括全局变量,但是父进程和子进程各有一份全局变量的拷贝,不能通过全局变量在父子进程
之间通信,而要通过专门的通信机制。
调用exec函数系列函数执行程序
exec系统函数并不创建新进程,调用exec前后的两个进程是相同的,exec系列的函数主要是为了清除父进程可执行代码的映像,用新的程序代码覆盖调用exec的进程代码。
如果exec代码执行成功,进程会从新程序的main函数入口开始执行,调用exec函数后除了进程ID保持不变下列属性也不变。
进程的父进程ID。
实际用户的ID和实际用户组ID。
进程组ID,会话ID,和控制终端。
定时器剩余时间
当前工作目录和根目录
文件创建掩码UMASK
进程的信号掩码。
调用system命令创建进程。
这个比较方便,system调用的时候,加载外部可执行程序,执行完毕后返回调用进程。system的返回码就是加载外部
函数原型
int system(_consr char *_command);
_command:要加载的外部程序的文件名。
返回值:
-1:执行失败,可以通过errno获得信息。
127.失败,在system的内部实现中,system首先fork子进程,然后调用exec执行新的shell,在shell内部也要执行要执行的程序,如果exec调用失败system返回127.由于要加载的
程序也可能返回127.所以最好先判断errno是否为0。
其他:执行成功。
进程的终止:
调用exit
exit实现带缓冲的IO操作,_exit实现不带缓冲的操作。
exit位于<stdlib.h>
_exit位于 <unistd.h>
调用wait等待进程退出
一个进程运行时,会向父进程发送SIGCLD信号,父进程收到后,可以选择忽略该信号或者安装信号处理函数处理该信号。而处理该信号就需要wait函数,wait是等待子进程退出
并且获取返回码,通常情况下父进程调用wait等待子进程退出,如果没有任何子进程退出,则wait默认进入阻塞态,直道调用的某个进程退出。
wait系列函数主要有两个
_pit_t wait(_WAIT_STATUS_stat_loc);
_pid_t waitpid(_pid_t_pid,int *_stat_loc,int _options);
位于:sys/wait.h