1. 进程标志符
ID=0 的进程---调度进程---也成为系统进程,进程ID =1的进程是init进程,init进程一般会接收孤儿进程,成为孤儿进程的父进程。
其他标志符可以通过函数返回值表示
#include<unistd.h>
pid_t getpid(void) ;
pid_t getppid(void) ;
uid_t getuid(void) ;
uid_t geteuid (void) ;
gid_t getgid (void) ;
gid_t getegid(void) ;
上面表示的p-进程 e--有效;u-用户 ;g--组;基本可以推出来了 。
2.创建进程--fork函数
#include<unistd.h>
pid_t fork (void) 子进程返回0;父进程返回子进程ID ,出错返回-1
在fork进程的过程中建议画图分析
# include "apue.h"
int glob = 8 ;
char buf [] = "a write to stdout \n";
int main (void)
{
int var ;
pid_t pid ;
var = 88 ;
if (write (STDOUT_FILENO,buf,sizeof(buf)-1) !=sizeof(buf)-1) //向标准输出写入字符
err_sys ("write error") ;
printf("before fork\n");
if ((pid = fork()) < 0){ //fork创建进程,返回两个值,子进程返回0,父进程返回子进程ID
err_sys("fork error");
}else if(pid == 0 ) {
glob++ ;
var++ ;//子进程执行程序变量++
}else {
sleep (2) ;//父进程休眠2秒,尽量避免与子进程竞争//
}
printf("pid = %d, glob =%d, var = %d\n",getpid(), glob, var );
}
fork之后对文件的处理方式:1.父进程休眠,等待子进程完成;2父子进程执行不同的程序段。
3.创建进程---vfork函数
函数原型:与fork相同的
不同点:1.vfork与fork共享同一段内存地址;2.vfork执行后直接调用exce函数,保证子进程执行
4.退出进程函数---exit函数
a._EXIT与_exit均直接退出,不对标准I/O流处理,但是exit清理标准I/O流,然后退出。
b.任何情况下父进程可以通过wait或者waitpid函数获得子进程终止状态。
c.如果子进程运行过程中,父进程终止,那么该子进程有init进程收养---父进程为init进程
d.僵死进程--就是子进程已经终止,但是父进程未对其进行处理(获取终止子进程的信息,释放资源)的进程就是僵死进程。
避免一个子进程成为僵死进程的方法就是fork两次
# include"apue.h"
# include <sys/wait.h>
int main(void)
{
pid_t pid ;
if ((pid = fork ())<0){
err_sys ("fork error");
} else if (pid == 0){ //产生就第第二个子进程
if ((pid = fork()) < 0)
err_sys("fork error");
else if (pid > 0)
_exit (0);
while (getppid()!=1) //子进程等待父进程终止
sleep (1); //第二个子进程休眠两秒,确保父进程已经安全退出,如果不退出的话父进程有可能不是init进程
printf ("second child,parent pid =%d\n",getppid());
exit (0);
}
if (waitpid(pid,NULL,0) !=pid)
err_sys("wait error") ;
exit (0);
}
执行结果如下:thinkpad@thinkpad:~/C_Pro/linux_ex$ second child,parent pid =1
5.父进程获取子进程是否终止状态---wait和waitpid函数
函数原型:
#include<sys/wait.h>
pid_t wait (int *statloc)
pid_t waitpid (pid_t pid, int *statloc, int option)`
成功返回进程PID,出错返回-1.
option的参数可以是0,也可是下表的或 P182.