fork可以在linux中创建子进程。先看man手册里面的东西:

SYNOPSIS
       #include <unistd.h>

pid_t fork(void);

DESCRIPTION
       fork()  creates  a new process by duplicating the calling process.  The
       new process, referred to as the child, is an  exact  duplicate  of  the
       calling  process,  referred  to as the parent    ......
RETURN VALUE
       On success, the PID of the child process is returned in the parent, and
       0  is returned in the child.  On failure, -1 is returned in the parent,
       no child process is created, and errno is set appropriately.

函数的作用的创建一个进程,这个函数会返回两次,可能有三种不同的返回值。 
1. 出错返回-1 
2. 返回0,表示是子进程 
3. 返回大于0,表示是父进程

下面的一个简单的实例:

#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/wait.h>#define CHILDCOUNT 1int main()
{ pid_t fpid[CHILDCOUNT ];int i = 0;for(i = 0; i < CHILDCOUNT; i++){fpid[i] = fork();if(fpid[i] < 0){   perror("fork");return -1;}else if(fpid[i] == 0){printf("This is child process, id:%d, my father:%d\n", getpid(), getppid());getchar();return 0;}else{printf("This is parent process, id:%d\n", getpid());}}getchar();printf("main() ------\n");return 0;
}

补充一点知识

  • fork出来的子进程复制了父进程的内存空间(处理代码区都复制了),和父进程共享代码区
  • fork之后,父子进程谁先执行不确定
  • 子进程中新定义的变量和父进程没有任何关系
  • 子进程也会复制父进程文件描述符,但是不会复制文件表。而是共用一个offset
  • 如果父进程先挂了,子进程就变成孤儿进程了,它爹就会变成1号进程
  • 子进程挂了会给父进程发信号(SIGCHLD),如果父进程收到该信号没有及时处理。子进程就变成僵尸进程了,直到父进程处理了该信号或父进程也退出了。

如何避免僵尸进程的出现?
如之前所说,父进程应该及时处理子进程发出来的信号,并且去获取子进程的退出码。 
在父进程中使用wait或waitpid参数等待子进程退出。 
也可以在收到子进程退出的信号时用wait或waitpid等待。

#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/wait.h>void sig_handle(int sig)
{int ret = 0;printf("%s() +++\n", __func__);
#if 0wait(NULL);
#elsewhile(ret = waitpid(-1, NULL, WNOHANG)){if(ret < 0){printf("waitpid failed\n");}else{printf("waitpid success\n");break;}}
#endif
}int main()
{signal(SIGCHLD, sig_handle); // 标记Apid_t fpid[5];int i = 0;for(i = 0; i < 5; i++){fpid[i] = fork();if(fpid[i] < 0){   perror("fork");return -1;}else if(fpid[i] == 0){printf("This is child process, id:%d, my father:%d\n", getpid(), getppid());return 0;}else{printf("This is parent process, id:%d\n", getpid());}}getchar();printf("main() ------\n");return 0;
}

假如没有signal(SIGCHLD, sig_handle);这个语句,函数运行时,5个子进程马上就结束了(父进程不能退出了)。这时候去查看可以看到有5个僵尸进程。 
如下:

xcy@xcy-virtual-machine:~/test/sock4$ ps -ef | grep test
xcy        5573   2863  0 16:53 pts/12   00:00:00 ./test
xcy        5574   5573  0 16:53 pts/12   00:00:00 [test] <defunct>
xcy        5575   5573  0 16:53 pts/12   00:00:00 [test] <defunct>
xcy        5576   5573  0 16:53 pts/12   00:00:00 [test] <defunct>
xcy        5577   5573  0 16:53 pts/12   00:00:00 [test] <defunct>
xcy        5578   5573  0 16:53 pts/12   00:00:00 [test] <defunct>
xcy        5580   3126  0 16:53 pts/0    00:00:00 grep --color=auto test
xcy@xcy-virtual-machine:~/test/sock4$

加上那句话就没有了

xcy@xcy-virtual-machine:~/test/sock4$ ps -ef | grep test
xcy        5587   2863  0 16:57 pts/12   00:00:00 ./test
xcy        5595   3126  0 16:57 pts/0    00:00:00 grep --color=auto test
xcy@xcy-virtual-machine:~/test/sock4$

再来一些有意思的东西
我们知道fork会出现两个进程,两个进程都会往下执行,看下面的代码:

#include<stdio.h>
#include<unistd.h>
int main()
{fork();fork();fork();printf("+\n");
}

这样就相当于最开始主进程创建两个进程A和B。 
A又创建两个进程A1,A2。B又创建两个进程B1,B2。 
最后,A1,A2,B1,B2都创建两个进程,所以最后会有8个进程,+会打印8次。 
这样就想细胞的二次分裂一样,3次分裂周期之后就有了8个细胞。

再来看个更难的:

#include<stdio.h>
#include<unistd.h>void fun()
{fork();// fork() || fork() && fork(); // 第一个fork返回大于0,后面两个就不执行了fork() && fork() || fork();fork();printf("+\n");
}int main()
{fun2();
}

这样一共能创建几个进程呢,+会打印几次呢。我们先一步一步来分析,假定所有的fork都会成功: 
第一次分裂成A和B。A进程创建的进程和B创建的进程数目肯定是一样的。

就先像下面这样分析:

fork() && fork() || fork(); // line 1
fork(); // line 2

要注意&&运算符和||运算符: 
对于&&来说:第一个表达式如果为0,后面的表达式就不用算了 
对于||来说:第一个表达式如果为1,后面的表达式也不用算了。 
为了更好分析,上面的fork一次标号为fork1,fork2,fork3,fork4。 
先看line1。fork1会返回一个非0,和一个0.

  • 1.返回0,则直接进入line2,fork4创建两个进程
  • 2.返回大于0,执行fork2。
  • 2.1 fork2返回0,则需要执行fork3,再接着执行fork4.这里会创建4个进程
  • 2.2 fork2返回大于0,也会执行fork3和fork4。相当于也创建4个进程。

综上,第一次的A进程会产生10个进程,同理,B也会有10个进程。所以一共会有20个进程。

转载于:https://www.cnblogs.com/xcywt/p/8111314.html

关于signal和fork的思考相关推荐

  1. 操作系统课程课程笔记

    第一章 概述 1.1 操作系统的定义 1.1.1 操作系统在计算机系统中所处位置 操作系统位于计算机硬件之上,系统工具之下的一层. 1.1.2 操作系统的定义 ​ 控制和管理计算机的软.硬件资源,合理 ...

  2. 玩转Nodejs的集群

    在Nodejs中使用集群还是不容易的.Javascript的单线程属性让nodejs下的应用很难使用现代机器的多核特性.比如下面的代码实现了一个http服务器的主干部分.这部分代码只会执行在一个线程上 ...

  3. gdbstub中的基本命令_GDB常用命令使用说明(一)

    本文由霸气的菠萝原创,转载请注明出处:http://www.cnblogs.com/xsln/p/gdb_instructions1.html GDB(GNU Debugger)是在Unix以及类Un ...

  4. Linux高级编程实验(30个)

    文章目录 1)输出Linux下的c也不是太难嘛!在linux下编辑,编译,运行 2)编写一个简单地c语言程序,根据输入的两个整数求平均值并且在终端输出,通过gcc编译器得到它的汇编程序文件. 3)编写 ...

  5. Libev documentation

    2019独角兽企业重金招聘Python工程师标准>>> NAME libev - a high performance full-featured event loop writte ...

  6. Linux相关实验总结

    文章目录 实验2 linux文件系统 实验一 open()系统调用 参数flags说明 参数mode说明 close()系统调用 read()/write()系统调用 lseek()系统调用 实验二 ...

  7. 《TCPIP网络编程》学习笔记

    第1章 理解网络编程和套接字 网络编程中接受连接请求的套接字创建过程: 第一步:调用socket函数创建套接字: 第一步:调用bind函数分配IP地址和端口号: 第三步:调用listen函数转为可接收 ...

  8. 嵌入式Linux C基本知识点总结

    学习这块知识点有好久了,最近借一本书的框架来对基本的知识点进行总结,参考<嵌入式Linux上的C语言编程实践>进行总结记录之. 一. 基本开发环境 Linux下C语言开发环境 使用工具:程 ...

  9. 子进程信号继承;kill+raise+alarm+pause+信号发生接收和处理+信号屏蔽

    子进程对父进程信号继承情况 fork创建子进程,但子进程没有exec 在fork子进程之前: 如果父进程调用signal设置了某个信号的处理方式的话,那么fork出的子进程会继承父进程对该信号设置的处 ...

最新文章

  1. java什么时候用有参_Java有陷阱——慎用入参做返回值
  2. javascript之function1
  3. 适用于Apache Hadoop 2.0 M5的Spring
  4. 一男子安装lua开发环境傻逼操作,惊呆所有人
  5. centos6.8 环境一键安装包 nginx配置thinkphp5
  6. ASP.NET MVC下使用AngularJs语言(一):Hello your name
  7. 从Python迁移到Go的原因和好处
  8. css radio 垂直居中显示,CSS表单元素垂直居中完美解决方案
  9. Jmeter安装+配置+运行
  10. Google Home其实是个错误
  11. 软件开发中的非功能需求类型
  12. 详解如何使用 PCem 安装 Windows 98 操作系统
  13. 数字电路加法器 基本原理(一)
  14. 用户权限---u+s\g+s\o+t三个特殊权限说明
  15. 驾校学员信息管理系统
  16. web开发入门_Web开发人员工作流程工具:入门指南
  17. 每日一道 LeetCode (4):罗马数字转整数
  18. 解决IE浏览器不支持es6语法Promise
  19. c语言使用time函数计时,C语言中的计时方法:time
  20. 数字图像处理(13): 形态学处理——图像开运算与图像闭运算

热门文章

  1. JAVA_Java常用核心包(概念)
  2. 活动目录实战系列六(win98客户端加入域)
  3. java 并发实例_java一些常用并发工具示例
  4. Vivadoz中Block Memory Generator v8.3的使用方法(二)
  5. Excel公式不同引用地址方式的应用总结
  6. React 教程:快速上手指南
  7. 阿里云推荐引擎使用教程
  8. python安装MySQLdb出错解决方案
  9. thinkphp 查找表并返回结果
  10. shell定时执行hive脚本文件