0号进程是空闲进程
1号进程是第一个用户进程
查看内核进程pid最大配置:cat /proc/sys/kernel/pid_max
**fork系统调用相关说明**
复制一个进程映象fork
使用fork函数得到的子进程从父进程的继承了整个进程的地址空间,包括:进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设置、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端等。
子进程与父进程的区别在于:
1、父进程设置的锁,子进程不继承
2、各自的进程ID和父进程ID不同
3、子进程的未决告警被清除;
4、子进程的未决信号集设置为空集。
fork系统调用
包含头文件 <sys/types.h> 和 <unistd.h>
函数功能:创建一个子进程
函数原型
pid_t fork(void);
参数:无参数。
返回值:
如果成功创建一个子进程,对于父进程来说返回子进程ID
如果成功创建一个子进程,对于子进程来说返回值为0
如果为-1表示创建失败
怎么样理解,一次调用,二次返回?
问题的本质是:两次返回,是在各自的进程空间中返回的。
子进程和父进程各有自己的内存空间 (fork:代码段、数据段、堆栈段、PCB进程控制块的copy)。
注意点:
理解1:fork系统调用之后,父子进程将交替执行。
理解2:怎么样理解一次调用2次返回?
答:是linux内核做的工作,因为不管是子进程还是父进程,都是各自在自己的内存空间中返回。
理解3:怎么样理解,fork返回值大于零的是父进程,为什么这样设计:?
答:因为父进程求子进程的pid比较困难,子进程求父进程的id比较容易。
理解4:怎么样理解分支在fork之后,而不是父进程main函数的开始?
答:因为父进程已经把环境搭建起来了,子进程只需要把父进程的数据段、代码段、堆栈段、PCB复制过来就可以了。
#if 1
int procnum = 10;
int loopnum = 100;
void TestFunc(int loopnum)
{
printf("loopnum:%d\n", loopnum);
}
//连续创建n个进程
void test()
{
int i = 0, j = 0;
printf("please enter you procNum : \n");
scanf("%d", &procnum);
printf("please enter you loopnum :\n");
scanf("%d", &loopnum);
pid_t pid;
//连续创建procnum个进程
for (i=0; i<procnum; i++)
{
pid = fork();
if (pid == 0)
{
for (j=0; j<loopnum; j ++)
{
TestFunc(j);
}
exit(0);
}
}
//wait(NULL);
printf("hello...\n");
}
#endif
//会打印多少个hello? 答案8个
#if 1
void test(void )
{
fork(); //会产生2个分支
fork(); //2个分支,运行fork函数,会产生4个分支。。4个进程
fork(); //4个进程运行fork调用,会产生8个分支。。。。
printf("hello...\n");
}
#endif
写时复制copy on write原则
如果多个进程要读取它们自己的那部分资源的副本,那么复制是不必要的。
每个进程只要保存一个指向这个资源的指针就可以了。
如果一个进程要修改自己的那份资源的“副本”,那么就会复制那份资源。这就是写时复制的含义
原因分析:加快速度,linux内核是段页式管理机制(因段管理从0开始,),也可叫页式管理机制。只复制对应的页。缺页,在中断查询,再赋值。
概念要深入理解
子进程要拷贝父进程的东西,但是只有在子进程使用自己的变量时,那是系统才是真正的拷贝,而拷贝的时候也不是机械的拷贝,不是将父进程的页全拷贝到子进程的页,而是只拷贝那个变量所占的页。
/*
孤儿进程和僵尸进程
如果父进程先退出,子进程还没退出那么子进程的父进程将变为init进程。(注:任何一个进程都必须有父进程)
如果子进程先退出,父进程还没退出,那么子进程必须等到父进程捕获到了子进程的退出状态才真正结束,
否则这个时候子进程就成为僵尸进程。
孤儿进程
如果父亲进程先结束,子进程会托孤给1号进程
*/
//测试僵尸进程
#if 1
int test(void )
{
pid_t pid;
printf("befor fork pid:%d \n", getpid());
int abc = 10;
pid = fork(); //errno
if (pid == -1)
{
perror("tile");
return -1;
}
if (pid > 0)
{
abc ++;
printf("parent: pid:%d \n", getpid());
printf("abc: %d \n", abc);
sleep(20);
}
else if (pid == 0)
{
abc ++;
printf("child: %d, parent: %d \n", getpid(), getppid());
printf("abc: %d \n", abc);
//sleep(100);
}
printf("fork after....\n");
return 0;
}
#endif
结果:
hzmct@U-64:~$ ps -ef| grep dm03_fork
hzmct 3789 3290 0 20:40 pts/8 00:00:00 ./dm03_fork
hzmct 3790 3789 0 20:40 pts/8 00:00:00 [dm03_fork] <defunct>(僵尸进程)
hzmct 3796 3687 0 20:40 pts/9 00:00:00 grep --color=auto dm03_fork
//测试孤儿进程
#if 1
int test(void )
{
pid_t pid;
printf("befor fork pid:%d \n", getpid());
int abc = 10;
pid = fork(); //errno
if (pid == -1)
{
perror("tile");
return -1;
}
if (pid > 0)
{
abc ++;
printf("parent: pid:%d \n", getpid());
printf("abc: %d \n", abc);
//sleep(20);
}
else if (pid == 0)
{
abc ++;
printf("child: %d, parent: %d \n", getpid(), getppid());
printf("abc: %d \n", abc);
sleep(100);
}
printf("fork after....\n");
return 0;
}
#endif
结果:
hzmct@U-64:~$ ps -ef| grep dm03_fork
hzmct 3818 1 0 20:45 pts/8 00:00:00 ./dm03_fork 托孤给了1号进程
hzmct 3820 3687 0 20:45 pts/9 00:00:00 grep --color=auto dm03_fork
查看僵尸进程
ps -e -o stat,ppid,pid,cmd | egrep '^[Zz]'
说明:
ps:ps命令用于获取当前系统的进程信息.
-e:参数用于列出所有的进程
-o:参数用于设定输出格式,这里只输出进程的stat(状态信息)、ppid(父进程pid)、pid(当前进程的pid),cmd(即进程的可执行文件。
egrep:是linux下的正则表达式工具
'^[Zz]':这是正则表达式,^表示第一个字符的位置,[Zz],表示z或者大写的Z字母,即表示第一个字符为Z或者z开头的进程数据,只所以这样是因为僵尸进程的状态信息以Z或者z字母开头。
(2)现在大多数linux系统,也会将僵尸进程标识为defunct,所以你也可以通过如下命令来获取僵尸进程信息。
ps -ef | grep "defunct"
//避免僵尸进程
#if 1
int test(void )
{
pid_t pid;
signal(SIGCHLD, SIG_IGN);//避免僵尸进程,即忽略子进程发给父进程的信号
printf("befor fork pid:%d \n", getpid());
int abc = 10;
pid = fork(); //errno
if (pid == -1)
{
//printf("pid < 0 err.\n");
perror("tile");
return -1;
}
if (pid > 0)
{
abc ++;
printf("parent: pid:%d \n", getpid());
printf("abc: %d \n", abc);
sleep(20);
}
else if (pid == 0)
{
abc ++;
printf("child: %d, parent: %d \n", getpid(), getppid());
printf("abc: %d \n", abc);
}
printf("fork after....\n");
return 0;
}
结果:
hzmct@U-64:~$ ps -ef| grep dm03_fork
hzmct 3838 3290 0 20:49 pts/8 00:00:00 ./dm03_fork
托孤给了session会话了
hzmct 3841 3687 0 20:49 pts/9 00:00:00 grep --color=auto dm03_fork
#endif