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

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. IDEA进行activiti-archetype-unittest脚手架的安装

    官网:https://www.activiti.org/ 第一步:下载activiti源码(https://github.com/Activiti/Activiti/tags) 第二步:在termin ...

  2. Java线程 : 线程同步与锁

    一.同步问题提出 线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. 例如:两个线程ThreadA.ThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据. public ...

  3. python爬虫4猫眼电影的Top100

    1 查看网页结构 (1)确定需要抓取的字段 电影名称 电影主演 电影上映时间 电影评分 (2) 分析页面结构 按住f12------->点击右上角(如下图2)---->鼠标点击需要观察的字 ...

  4. .Net 配置 swagger 使用nginx反向代理后请求带端口号导致无法正常访问---解决方法

    1 webconfig中 appsetting 中增加配置 <appSettings> <add key="aspnet:UseHostHeaderForRequestUr ...

  5. ceph架构简介

    ceph架构简介 在测试OpenStack的后端存储时,看到了ceph作为后端存储时的各种优势 ,于是查询资料,总结了这篇ceph架构的博客,介绍了ceph的架构和ceph的核心组件.ceph整体十分 ...

  6. Windows平台为 ElasticSearch 6.x 安装 Head 客户端插件

    背景知识 ES 5.x 以上版本安装 head 需要 node 和 grunt 环境(之前的直接用plugin命令即可安装). 操作步骤 1. 安装 ElasticSearch 6.x,访问 http ...

  7. JavaWeb实现增删查改(图书信息管理)之删除功能实现

    —————————————————————————————————————————————————————————— 删除按钮对应的servlet -->DeleteBooks.java  ↓ ...

  8. Java开发笔记(一百一十八)AWT按钮

    前面介绍了如何通过AWT显示程序的窗口界面,那么要怎样在该窗口上面添加丰富多样的控件呢?注意Frame类是个窗口工具,它由窗楣(标题栏)与窗体(窗口主界面)两部分组成,故而Frame类只对整个窗口统筹 ...

  9. 数组中重复的数字(Python)

    #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2019-08-13 22:35 # @Author : daryl # @File : ...

  10. leetcode无重复字符的最长子串

    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc&qu ...