今天继续研究进程相关的东东,话不多说,进入正题:

SIGCHLD:
关于它,之前章节的学习中已经用到了,具体可以参考博文:http://www.cnblogs.com/webor2006/p/3500972.html,这里会进一步来理解它:
 
说明:关于信号,很快就会有一个专题来仔细研究它,现在可以简单认为:它是一种异步通知事件
说明:如果父进程没有查询子进程的退出状态,子进程是没有办法真正完全退出的,这时子进程的状态就称为僵尸状态,该进程就叫僵尸进程
下面就对这两个函数进行详析:
wait:
 
下面用具体代码来进行说明:
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>//提供wait函数声明

#include <sys/types.h>
#include <fcntl.h> #include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while() int main(int argc, char *argv[])
{
pid_t pid;
pid = fork();
if (pid == -)
ERR_EXIT("fork error"); if (pid == )
{
sleep();//子进程休眠,是为了看到父进程会等待子进程退出
printf("this is child\n");
exit();
} printf("this is parent\n");
int status;
wait(&status);等待子进程退出
return ;
}

看一下编译运行效果,下面用动画来展现,以便能体现到wait的意义:

从图中可以感受到,父进程虽然是已经输出了,但是一直是等到子进程退出了才退出,这也就是wait会让父进程去查子进程的退出状态,从而避免了僵尸进程的出现。

编译运行:

对于这些状态信息,可以通过调用系统宏来查询,下面具体来介绍下:

用来代码来解释:

编译运行:

下面我们可以用abort函数,来模拟子进程非法退出的情况:

这时再编译运行:

实际上,对于子进程非法退出的,还可以判断得再仔细一些,因为有好几种情况可以造成子进程非法退出,如上图所示,一是因为捕获信号而终止,二是被暂停了,具体用法如下:

编译运行:

关于信号,由于还没有学到,所以暂停的信号就不多说了,这里就不演示暂停信号的情况了,重在理解一下获取子进程退出状态信息的用法

【说明:上面的这些宏在sys/wait.h头文件里定义

waitpid:
对于上面刚学完的wait,它是等待随意的进程退出,因为一个父进程可以有多个子进程,如果只要有一个子进程退出,父进程的wait就会返回;
而waitpid则可以等待特定的进程退出,这是两者的区别,下面就来具体学习下这个函数的用法:
 
对于waitpid的pid参数的解释与其值有关:
实际上可以通过查看man帮助得到这个信息:
可以将我们之前的程序用waitpid替换一下,效果一样:
 
也同样,用它来改装我们之前的程序,对于父进程,实际上只有一个子进程,就可以直接传子进程的id既可,只等待这个子进程:
效果一样:
 
比如:waitpid(-100,&status,0)的意思就是,等待进程组ID=100里面的任一一个子进程。
 
最后,关于wait和waitpid,进行一个总结:
 另外,对于僵进程,已经被提到过好几次了,最后再来总结一下:

僵进程:
如何避免僵进程:
system:
 
实际上,它就等于用代码去执行我们在命令行中敲的那些shell命令,下面就以实际代码来认识这个函数的使用:
编译运行:
实际上,system()函数是调用"/bin/sh -c",如下:
对于这个函数的使用,其实没什么难的,但是这个函数很有代表性,我们可以通过它来综合运用我们所学习东西,这样其实还是挺有意义的,接下来,会自己实现一个跟system同样的功能,来达到理解system函数的实现原理:
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h> #include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while() int my_system(const char *command);//自己实现有system函数声明 int main(int argc, char *argv[])
{
my_system("ls -l | wc -w");//这里改用自己实现在system
return ;
} int my_system(const char *command)
{
pid_t pid;
int status;
if (command == NULL)
return ;
  if ((pid = fork()) < )
status = -;//出现不能执行system调用的其他错误时返回-1
  else if (pid == )
{//子进程
execl("/bin/sh", "sh", "-c", command, NULL);//替换成sh进程
exit();//如果无法启动shell运行命令,system将返回127,因为如果成功替换了之后,是不会执行到这句来的
    }
else
{//父进程会等到子进程执行完
while (waitpid(pid, &status, ) < )
{
if (errno == EINTR)//如果是被信号打断的,则重新waitpid
continue; status = -;
break;
}
     //这时就顺利执行完了
} return status;
}

编译运行:

可见,通过自己实现的system,就能够大致弄清楚它的原理,虽说程序比较少,但是五脏俱全,因为可以把自己学过的知识给运用起来。

好了,今天的学习就到这,下次见。

linux系统编程之进程(四)的更多相关文章

  1. linux系统编程之进程(一)

    今天起,开始学习linux系统编程中的另一个新的知识点----进程,在学习进程之前,有很多关于进程的概念需要了解,但是,概念是很枯燥的,也是让人很容易迷糊的,所以,先抛开这些抽象的概念,以实际编码来熟 ...

  2. linux系统编程之进程(六):父进程查询子进程的退出,wait,waitpid

    本节目标: 僵进程 SIGCHLD wait waitpid 一,僵尸进程 当一个子进程先于父进程结束运行时,它与其父进程之间的关联还会保持到父进程也正常地结束运行,或者父进程调用了wait才告终止. ...

  3. linux系统编程之进程(五)

    今天继续学习系统编程,学习的主题还是进程,今天主要讨论的是守护进程相关的概念,开始进入正题: 什么是守护进程:       守护进程的创建步骤: 在描述它之前,首先得先了解两个概念:进程组.会话期: ...

  4. linux系统编程之进程(二):进程生命周期与PCB(进程控制块)

    本节目标: 进程状态变迁 进程控制块 进程创建 进程撤消 终止进程的五种方法 一,进程状态变迁 进程的三种基本状态 就绪(Ready)状态 当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便 ...

  5. linux系统编程之进程(八):守护进程详解及创建,daemon()使用

    一,守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.它不需要用户输入就能运行而且提供某种服务,不是对整个 ...

  6. Linux系统编程——Daemon进程

    目录 Daemon进程介绍 前提知识 Daemon进程的编程规则 Daemon进程介绍 Daemon运行在后台也称作"后台服务进程". 它是没有控制终端与之相连的进程.它独立与控制 ...

  7. linux系统编程之进程(三):进程复制fork,孤儿进程,僵尸进程

    本节目标: 复制进程映像 fork系统调用 孤儿进程.僵尸进程 写时复制 一,进程复制(或产生)      使用fork函数得到的子进程从父进程的继承了整个进程的地址空间,包括:进程上下文.进程堆栈. ...

  8. linux系统编程--守护进程,会话,进程组,终端

    终端: 在UNIX系统中,用户通过终端登录系统后得到一个Shell进程,这个终端成为Shell进程的控制终端(Controlling Terminal), 进程中,控制终端是保存在PCB中的信息,而f ...

  9. Linux系统编程之进程概念

    注:本文部分图片来源于网络,如有侵权,请告知删除 1. 什么是进程? 在了解进程概念之前,我们需要先知道程序的概念. 程序,是指编译好的二进制文件,这些文件在磁盘上,并不占用系统资源. 进程,指的是一 ...

随机推荐

  1. mysql instr()函数

    1)instr()函数的格式  (俗称:字符查找函数) 格式一:instr( string1, string2 )    /   instr(源字符串, 目标字符串) 格式二:instr( strin ...

  2. harbor镜像仓库-https访问配置

    1. 证书的生成 在测试或开发环境中,您可以选择使用自签名证书,而不是来自受信任的第三方CA的证书.以下内容将向您展示如何创建自己的CA,并使用您的CA签署服务器证书和客户端证书.   1.1 生成c ...

  3. 【Python开发】【编程开发】各种系统的清屏操作命令

    mac os x terminal清屏快捷键 cammand+k linux系统清屏快捷键 ctrl+l linux系统命令行清屏命令 clear windows 命令行清屏命令 cls Matlab ...

  4. oracle创建用户并指定表空间

    /*第1步:创建ODPS数据表空间 */create tablespace ODPS logging datafile '/home/oracle/tablespace_dir/ODPS.dbf' s ...

  5. spring mvc 参数类型转换

    实现方式以字符串转Date为例说明: 全局配置 第一种:实现 Converter 接口 实现类: public class StringToDateConveter implements Conver ...

  6. java的Array和List相互转换

    1.Array转List,通过java.util.Arrays.asList(T... a)参数是可变泛型参数 注意,Arrays.asList返回的类型是不可变长度的集合,底层是final修饰的泛型 ...

  7. Kubernetes集群安装(自己搭过,已搭好)

    k8s安装目录 1. 组件版本 && 集群环境 组件版本 etcd 集群 && k8s master 机器 && k8s node 机器 集群环境变量 ...

  8. Docker部署ELK 7.0.1集群之Elasticsearch安装介绍

    elk介绍这里不再赘述,本系列教程多以实战干货为主,关于elk工作原理介绍,详情查看官方文档. 一.环境规划 主机名 IP 角色 节点名 centos01 10.10.0.10 es node-10 ...

  9. Automatically generating nice graphs at end of your Load Test with Apache JMeter and JMeter-Plugins

    Update as of November 2017: Since JMeter 3.0, last version being 3.3, JMeter provides Out Of The Box ...

  10. java之初识hibernate

    1. 使用jdbc进行数据库操作:获取数据库连接,编写sql语句,执行sql操作,关闭连接. 比如:每次创建连接,释放资源----使的执行效率降低: 解决方案:连接池. 编写sql语句动作----简单 ...