Linu系统编程---9(SIGCHLD 信号,信号传参,中断系统调用)

SIGCHLD 信号

SIGCHLD 的产生条件

  1. 子进程终止时
  2. 子进程接收到 SIGSTOP 信号停止时
  3. 子进程处在停止态,接受到 SIGCONT 后唤醒时

借助 SIGCHLD 信号回收子进程

子进程结束运行,其父进程会收到 SIGCHLD 信号。该信号的默认处理动作是忽略。可以捕捉该信号,在捕捉函 数中完成子进程状态的回收。

linux系统根据未决信号集来处理信号,多个信号进入未决信号集只处理一次。

#include<stdio.h>                                                                    
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<signal.h>//出错处理函数
void sys_err(char * str)
{perror(str);exit(1);
}void do_sig_child(int signo)
{int status;//传出参数pid_t pid;//进程ID//status子进程退出状态while((pid = waitpid(0,&status,WNOHANG))>0){if(WIFEXITED(status))printf("--------child %d exit %d\n",pid,WEXITSTATUS(status));else if(WIFSIGNALED(status))printf("child %d cancel signal %d\n",pid,WTERMSIG(status));}   
}int main(void)
{pid_t pid;int i;//阻塞SIGCHLDfor(i=0;i<10;i++){if((pid = fork()) == 0){ break;}else if(pid<0){sys_err("fork");}}if(pid == 0){int n=1;while(n--){printf("child ID %d\n",getpid());sleep(1);}return i+1;}else if(pid >0 ){//有可能再注册信号过程中子进程死亡,所以要先对SIGCHILD信号进程阻塞//SIGCHILD阻塞struct sigaction act;act.sa_handler = do_sig_child;sigemptyset(&act.sa_mask);act.sa_flags = 0;sigaction(SIGCHLD,&act,NULL);//解除对SIGCHLD的阻塞while(1){printf("Parent ID %d\n",getpid());sleep(1);}}return 0;
}          

在这里插入图片描述

子进程结束 status 处理方式

pid_t	waitpid(pid_t		pid,int*	status,int	options) 
  1. options
    WNOHANG
    没有子进程结束,立即返回
    WUNTRACED
    如果子进程由于被停止产生的 SIGCHLD,waitpid 则立即返回
    WCONTINUED
    如果子进程由于被 SIGCONT 唤醒而产生的 SIGCHLD,waitpid 则立即返回
  2. 获取 status
    WIFEXITED(status)
    子进程正常 exit 终止,返回真
    WEXITSTATUS(status)返回子进程正常退出值
    WIFSIGNALED(status)
    子进程被信号终止,返回真
    WTERMSIG(status)
    返回终止子进程的信号值
    WIFSTOPPED(status) 子进程被停止,返回真
    WSTOPSIG(status)返回停止子进程的信号值 WIFCONTINUED(status)

SIGCHLD 注意

  1. 子进程继承了父进程的信号屏蔽字和信号处理动作,但子进程没有继承未决信号集 spending。
  2. 注意注册信号捕捉函数的位置。
  3. 应该在 fork 之前,阻塞 SIGCHLD 信号。注册完捕捉函数后解除阻塞。

信号传参

发送信号传参

sigqueue 函数对应 kill 函数,但可在向指定进程发送信号的同时携带参数 int sigqueue(pid_t pid,int sig,const union sigvalvalue);成功:0;失败:-1,设置

errno union	sigval
{ int sival_int;void*sival_ptr;//这个地址给本进程使用
};

向指定进程发送指定信号的同时,携带数据。但,如传地址,需注意,不同进程之间虚拟地址空间各自独立, 将当前进程地址传递给另一进程没有实际意义。

捕捉函数传参

int	sigaction	(int	signum,const	struct	sigaction*act,struct	sigaction*oldact);structsigaction{ void       (*sa_handler)(int); void  	 (*sa_sigaction)(int,siginfo_t*,void*); sigset_t 	sa_mask;int 	sa_flags; void 	(*sa_restorer)(void);}; 

当注册信号捕捉函数,希望获取更多信号相关信息,不应使用 sa_handler 而应该使用 sa_sigaction。但此时的 sa_flags 必须指定为 SA_SIGINFO。siginfo_t 是一个成员十分丰富的结构体类型,可以携带各种与信号相关的数据。

中断系统调用

系统调用可分为两类:慢速系统调用其他系统调用。

慢速系统调用:

可能会使进程永远阻塞的一类。如果在阻塞期间收到一个信号,该系统调用就被中断,不再 继续执行(早期);也可以设定系统调用是否重启。如,read、write、pause、wait…

其他系统调用:

getpid、getppid、fork…

结合 pause,
回顾慢速系统调用:
慢速系统调用被中断的相关行为,实际上就是 pause 的行为:
如,read

  1. 想中断 pause,信号不能被屏蔽。
  2. 信号的处理方式必须是捕捉 (默认、忽略都不可以)
  3. 中断后返回-1,
    设置 errno 为 EINTR(表“被信号中断”) 可修改 sa_flags 参数来设置被信号中断后系统调用是否重启。SA_INTERRURT 不重启。 SA_RESTART 重启。

sa_flags 还有很多可选参数,适用于不同情况。如:捕捉到信号后,在执行捕捉函数期间,不希望自动阻塞该 信号,可将 sa_flags 设置为 SA_NODEFER,除非 sa_mask 中包含该信号。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/383231.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linu系统编程---10(Linux的终端,线路规程,网络终端,进程组)

终端 输入输出设备的总称 在 UNIX 系统中&#xff0c;用户通过终端登录系统后得到一个 Shell 进程&#xff0c;这个终端成为 Shell 进程的控制终端&#xff08;Controlling Terminal&#xff09;&#xff0c; 进程中&#xff0c;控制终端是保存在 PCB 中的信息&#xff0c;而 …

Linux系统编程---11(会话,守护进程,创建守护进程)

会话 创建会话 创建一个会话需要注意以下6点注意事项 调用进程不能是进程组组长&#xff0c;该进程变成新会话首进程该进程成为一个新进程组的组长进程需要root权限&#xff08;nbuntu不需要&#xff09;新会话丢弃原有的控制终端&#xff0c;该会话没有控制终端该调用进程是…

Linux系统编程----12(线程概念,Linux线程实现原理,栈中ebp指针和ebp指针,线程的优缺点和共享资源)

线程概念 什么是线程 在一个程序里的一个执行路线就叫做线程&#xff08;thread&#xff09;。更准确的定义是&#xff1a;线程是“一个进程内部的控制序列” 一切进程至少都有一个执行线程线程在进程内部运行&#xff0c;本质是在进程地址空间内运行在Linux系统中&#xff0…

Linux系统编程---13(线程控制函数,创建线程,循环创建多个线程,线程间共享全局变量)

线程控制 操作系统并没有提供创建线程的系统调用接口&#xff0c;因此大佬们封装了一个线程的接口库实现线程控制。意为着用户创建线程都使用的是库函数&#xff08;所以有时候我们说创建的线程是一个用户态线程&#xff0c;但是在内核中对应有一个轻量级进程实现线程程序的调…

Linux系统编程---14(回收子线程,回收多个子线程,线程分离,杀死线程)

回收子线程 pthread_join 函数 阻塞等待线程退出&#xff0c;获取线程退出状态 其作用&#xff0c;对应进程中 waitpid() 函数。 int pthread_join (pthread_t thread,void** retval); 成功&#xff1a;0&#xff0c;失败&#xff1a;错误号 参数&#xff1a;thread&#x…

Linux系统编程----15(线程与进程函数之间的对比,线程属性及其函数,线程属性控制流程,线程使用注意事项,线程库)

对比 进程 线程 fork pthread_create exit (10) pthread_exit &#xff08;void *&#xff09; wait (int *) pthread_join &#xff08;&#xff0c;void **&#xff09;阻塞 kill pthread_cancel ();必须到取消点&#xff08;检查点&#xff09;&#xff1a;…

Linux系统编程----16(线程同步,互斥量 mutex,互斥锁的相关函数,死锁,读写锁)

同步概念 所谓同步&#xff0c;即同时起步&#xff0c;协调一致。不同的对象&#xff0c;对“同步”的理解方式略有不同。如&#xff0c;设备同步&#xff0c;是指在两 个设备之间规定一个共同的时间参考&#xff1b;数据库同步&#xff0c;是指让两个或多个数据库内容保持一致…

Linux系统编程---17(条件变量及其函数,生产者消费者条件变量模型,生产者与消费者模型(线程安全队列),条件变量优点,信号量及其主要函数,信号量与条件变量的区别,)

条件变量 条件变量本身不是锁&#xff01;但它也可以造成线程阻塞。通常与互斥锁配合使用。给多线程提供一个会合的场所。 主要应用函数&#xff1a; pthread_cond_init 函数pthread_cond_destroy 函数pthread_cond_wait 函数pthread_cond_timedwait 函数pthread_cond_signa…

Linux系统编程---18(线程池相关概念及其实现)

线程池 概念&#xff1a; 一堆线程任务队列 作用 避免大量线程频繁的创建/销毁时间成本避免瞬间大量线程创建耗尽资源&#xff0c;程序崩溃危险 实现 创建固定数量的线程创建一个线程安全的任务队列 一种线程使用模式。 线程过多会带来调度开销&#xff0c;进而影响缓…

设计模式--1(设计模式基础,设计模式基本原则,设计模式分类)

设计模式基础 模式 在一定环境中解决某一问题的方案&#xff0c;包括三个基本元素–问题&#xff0c;解决方案和环境。大白话&#xff1a;在一定环境下&#xff0c;用固定套路解决问题。 设计模式 是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使…

设计模式----2(简单工厂模式的概念,简单工厂模式的实现,简单工厂模式的优缺点)

简单工厂模式 简单工厂模式的概念 简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式。通过专门定义一个类来负 责创建其他类的实例&#xff0c;被创建的实例通常都具有共同的父类。 具体分类 工厂&#xff08;Creator&#xff09;角色 简单工厂模式的核心&#xff0…

设计模式---3(工厂方法模式的概念,工厂方法模式的实现,工厂方法模式和简单工厂模式比较)

工厂方法模式 概念 工厂方法模式同样属于类的创建型模式又被称为多态工厂模式 。 工厂方法模式的意义 定义一个创建产品对象的工厂接口&#xff0c;将实际创建工作推迟到子类当中。 核心工厂类不再负责产品的创建&#xff0c;这样核心类成为一个抽象工厂角色&#xff0c;仅…

设计模式---4(抽象工厂模式的概念,产品组和产品等级的概念,抽象工厂模式的实现)

抽象工厂模式 抽象工厂模式的概念 抽象工厂模式是所有形态的工厂模式中最为抽象和最其一般性的。抽象工厂模式可以向 客户端提供一个接口&#xff0c;使得客户端在不必指定产品的具体类型的情况下&#xff0c;能够创建多个产品 族的产品对象。 抽象工厂的角色及其职责 抽象工…

1.c++中初始化列表和构造函数初始化的区别是什么?2.类的成员变量的初始化顺序是按照声明顺序吗?

初始化列表和构造函数初始化的区别是什么&#xff1f; 初始化和赋值对内置类型的成员没有太大的区别&#xff0c;在成员初始化列表和构造函数体内进行&#xff0c;在性能和结果上都是一样的。只有一些需要注意的事项 初始化列表一般情况如下&#xff1a; Date(int year, int …

设计模式---5(建造者模式的概念及其实现,建造者模式的角色与职责,建造者模式和工厂模式的区别)

建造者模式 建造者模式的概念 Builder 模式也叫建造者模式或者生成器模式&#xff0c;是由 GoF 提出的 23 种设计模式中的一种。 Builder 模式是一种对象创建型模式之一&#xff0c;用来隐藏复合对象的创建过程&#xff0c;它把复合对象的 创建过程加以抽象&#xff0c;通过子…

system阻塞SIGCHLD信号原因

system阻塞SIGCHLD信号原因 标签&#xff1a; c 2014-11-08 11:58 198人阅读 评论(0) 收藏 举报 分类&#xff1a; linux编程&#xff08;1&#xff09; 代码1&#xff1a;APUE10.18节的system函数源代码 int system(const char *cmdstring) /* with appropriate signal ha…

设计模式6---(单例模式的概念及其实现(懒汉式和饿汉式),线程安全)

单例模式 单例模式的概念 单例模式是一种对象创建型模式&#xff0c;使用单例模式&#xff0c;可以保证为一个类只生成唯一的实例对象。也就是说&#xff0c;在整个程序空间中&#xff0c;该类只存在一个实例对象。 GoF 对单例模式的定义是&#xff1a;保证一个类、只有一个实…

套接字编程---2(TCP套接字编程的流程,TCP套接字编程中的接口函数,TCP套接字的实现,TCP套接字出现的问题,TCP套接字多进程版本,TCP套接字多线程版本)

TCP模型创建流程图 TCP套接字编程中的接口 socket 函数 #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int socket(int domain, int type, int protocol); domain: AF_INET 这是大多数用来产生socket的协议&#xff0c;使用TCP或UDP来传输&…

Linux中netstat工具详解

简介 Netstat 命令用于显示各种网络相关信息&#xff0c;如网络连接&#xff0c;路由表&#xff0c;接口状态 (Interface Statistics)&#xff0c;masquerade 连接&#xff0c;多播成员 (Multicast Memberships) 等等。 常见参数 -a (all)显示所有选项&#xff0c;默认不显示…

网络基础 2-1(应用层,HTTP三点注意,HTTP协议格式, 最简单的HTTP服务器)

应用层 应用层 负责应用程序之间的数据沟通-----协议都是用户自己定的 自定制协议&#xff1a; 结构化数据传输 序列化&#xff1a; 将数据对象以指定的协议&#xff08;数据格式&#xff09;进行可用于持久化存储或者数据传输时的数据组织 例如在分布式的系统中&#xf…