C语言 sigchild回收子进程
// 、、使用内存映射可以拷贝文件
/*
对原始文件进行内存映射
创建一个新文件
把新文件的数据拷贝映射到内存中
通过内存拷贝将第一个文件的内存映射区拷贝到第二个文件的内存映射区
释放资源
*/// 匿名映射,不需要文件实体来进行内存映射
// 只能用于有血缘关系的进程间通信
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
// int main()
// {/*
// kill函数
// pid》0将信号发送给指定进程
// =0:将信号发送给当前进程组
// =-1:将信号发送给每一个有权限接受这个信号的进程
// 《-1:进程组id的绝对值
// sig,要发送的信号
// kill(getppid(), 9);
// kill(getpid(), 9);
// raise函数,给当前进程发送信号
// sig,要发送的信号,成功返回0,失败返回非0*/
// alarm函数
// 设置定时器,倒计时,当时间为0的时候,会给当前进程发送一个 SIGALARM信号
// 取消定时器,alarm(0)即可
// 返回值是unsigned int,倒计时剩余的时间(上一个alarm剩余的时间)
// SIGALRARM信号默认终止当前进程,每个进程只能设置一个定时器
// int seconds = alarm(5);
// printf("%d\n", seconds);
// sleep(2);
// seconds = alarm(3);
// printf("%d\n", seconds);
// while(1){// }
// 1秒钟电脑能输多少个数?
//无论进程处于什么状态,alarm都会正常计时
// 实际时间=内核时间+用户时间+io消耗的时间
// alarm(1);
// int i =0;
// while(1){// printf("%d\n",i++);
// }// settimeer函数,用于替换alarm函数,且精度比alarm要高很多,
// 参数
// which,定时器以什么时间计时
// ITIME_REAL: 真实时间,时间到达,就发送SIGALRM
// ITIME_VIRTUAL;用户时间,时间到达就发送SIGVTALRM
// ITIMER_PROF:进程在内核状态下消耗的时间
// 过3秒后,每两秒执行一次
// struct itimerval new_value;
// // 设置值
// new_value.it_interval.tv_sec = 2;
// new_value.it_interval.tv_usec =0;
// new_value.it_value.tv_sec=3;
// new_value.it_value.tv_usec=0;
// int ret = setitimer(ITIMER_REAL,&new_value,NULL);
// printf("定时器开始\n");
// if (ret==-1){// perror("settimer");
// exit(0);
// }
// getchar();
// signal捕获信号
// sigkill,sigstop既不能被捕捉也不能被忽略
// signum:要捕捉的信号
// handler:捕捉到信号之后如何处理
// sig_ign:忽略
// sig_dfl:使用信号默认的行为
// 回调函数:捕获到信号后执行该函数
// 过3秒后,每两秒执行一次
// 注册信号捕捉函数
//忽略信号
// signal(SIGALRM,SIG_IGN);
//直行信号的默认动作(sig_ALRM结束程序)
// signal(SIGALRM,SIG_DFL);
// void (*sig_handler)(int),这是一个函数指针。返回void,参数int,函数名称:sig_handler
void sig_handler(int num) {printf("捕获到了信号:%d\n", num);printf("lllllllllllllll]n");
}// 信号集
// 产生但是还没有被处理的信号被归到未决信号集// sigint信号状态被存储在第二个bit位上
// bit位为1,说明信号处于未决状态
// 未决状态对的信号需要备处理
// 但是在处理之前需要和另一个叫做阻塞信号集的对应比特位进行比较
// 如果对应位置是1,那么就说明信号被阻塞,那么这个信号就不会被处理,直到指变成0
// 阻塞信号集默认不阻塞任何信号,我们可以手动进行设置(调用系统API)// sigemptyset函数
// 清空信号集中的数据,所有标志位被设置为0
// 参数:set,要设置的信号集
// sigfillset函数
// 设为1
// sigaddset函数
// 设置信号集中的某一个标志位设置为1
// sigdelset 函数
// 和上面的相反,0
// sigismember函数
// 判断某个信号是否阻塞
// 上面的函数都是阻塞信号集的操作函数
// 创建一个信号集
// sigset_t set ;
// // 先清空
// sigemptyset(&set);
// // 判断信号是否在信号集中
// int ret = sigismember(&set,SIGINT);
// if (ret == 0) {// printf("SIGINT 不阻塞\n");
// }else if(ret == 1) {// printf("SIGINT 阻塞\n");// }
// // 添加信号到信号集中
// sigaddset(&set,SIGINT);
// sigaddset(&set,SIGQUIT);
// ret = sigismember(&set,SIGINT);
// if (ret == 0) {// printf("SIGINT 不阻塞\n");
// }else if(ret == 1) {// printf("SIGINT 阻塞\n");// }
// ret = sigismember(&set,SIGQUIT);
// if (ret == 0) {// printf("SIGQUIT 不阻塞\n");
// }else if(ret == 1) {// printf("SIGQUIT 阻塞\n");// }
// sigdelset(&set, SIGQUIT);
// ret = sigismember(&set,SIGQUIT);
// if (ret == 0) {// printf("SIGQUIT 不阻塞\n");
// }else if(ret == 1) {// printf("SIGQUIT 阻塞\n");// }
// 系统调用设置信号集
// sigprocmask
// 该函数可以将我们自定义的信号集映射到内核中
// how:
// 如何对内核中的阻塞信号集进行处理
// sig_block,mask|set
// SIG_UNBLOCK: mask^set(异或操作
// sig_setmask 覆盖内核的指
// sigpending
// 获取内核当中的未决信号集// 编写一个程序,将所有的常规信号(1-31)的未决状态打印出来
// 设置某些信号是阻塞的,通过键盘来产生这些信号ctrl+?
// 设置2、3信号阻塞
// sigset_t set;
// sigemptyset(&set);
// // 将2、3信号添加到信号集中
// sigaddset(&set,SIGINT);
// sigaddset(&set,SIGQUIT);
// //修改内核中的阻塞信号集
// sigprocmask(SIG_BLOCK,&set, NULL);
// int num=0;
// while(1) {// printf("num:%d\n",num);
// if(num == 10){// // 解除sigint的阻塞
// sigprocmask(SIG_UNBLOCK,&set,NULL);
// }
// num++;
// // 获取当前的未决信号集
// sigset_t pendingset;
// sigemptyset(&pendingset);
// sigpending(&pendingset);
// //遍历bit位
// for(int i=1;i<=32;i++) {// if(sigismember(&pendingset,i)==1){// printf("1");
// }else if(sigismember(&pendingset, i)==0) {// printf("0");
// }else{// perror("sigismember\n");exit(0);
// }// }printf("\n");sleep(1);
// }
// sigaction
// 检查或者改变信号的处理方式
// signum,需要捕捉的信号
// act,捕捉到信号后需要执行的动作
// oldaact,没用// struct sigaction
// sa_handle:回调函数指针// 临时阻塞信号集
// sa_mask
// 临时阻塞某些信号// 使用那个信号处理对信号进行处理。如果是0表示使用回调函数
// // 必须在设置定时器之前注册回调函数
// 最好使用sigaction去注册回调函数
// struct sigaction act;
// act.sa_flags = 0;
// act.sa_sigaction = sig_handler;
// //清空临时阻塞信号集
// sigemptyset(&act.sa_mask);
// sigaction(SIGALRM,&act,NULL);
// // sig_t retr = signal(SIGALRM,sig_handler);
// // if(retr==SIG_ERR) {// // perror("signal注册");
// // exit(-1);
// // }
// struct itimerval new_value;
// // 设置值
// new_value.it_interval.tv_sec = 2;
// new_value.it_interval.tv_usec =0;
// new_value.it_value.tv_sec=3;
// new_value.it_value.tv_usec=0;
// int ret = setitimer(ITIMER_REAL,&new_value,NULL);
// printf("定时器开始\n");
// if (ret==-1){// perror("settimer");
// exit(0);
// }
// // getchar();
// // while(1);
// sigchild信号产生的条件
// 子进程终止
// 子进程接收到sigstop信号停止
// 子进程处于停滞状态,收到sigcont后唤醒
// 父进程默认葫芦该信号
// 可以用于解决僵尸进城的问题
void sig_handler2(int num){printf("捕捉奥得信号:%d\n",num);// 回首紫禁城// while(1){// wait(NULL);}while (1){int ret =waitpid(-1,NULL,WNOHANG);/* code */if(ret>0){printf("二字挂了:%d\n", ret);}else if(ret ==0) {// 说明还有子进程或者break;}else if(ret ==- 1){// 没有紫禁城了break;}}}
int main()
{pid_t pid;
int count=20;
for (size_t i = 0; i < count; i++)
{pid = fork();if(pid==0){break;}/* code */}
// 捕捉子进程死亡时发送的sigchild信号
struct sigaction act;
act.sa_flags=0;
act.sa_sigaction = sig_handler2;
sigemptyset(&act.sa_mask);
sigaction(SIGCHLD,&act,NULL);
if(pid>0){// 父进程while(1){printf("我是你爹\n");sleep(2);}} else if(pid==0){printf("儿字:%d\n",getpid());}// pid_t pid = fork();
// if(pid==0){// for(int i=0;i<5;i++) {// printf("孩子进程%d\n", i);
// sleep(1);
// }
// }else if(pid>0) {// printf("爹进程\n");
// sleep(2);
// printf("傻儿子\n");
// kill(pid,SIGINT);
// }
return 0;}
/*// char * buf;// strcpy(buf, "cao nima");return 0;}/*// 修改mmap的flags参数,之前使用的是MAP_SHARED// 现在我们要用的是MAP_ANONint len = 1204;void *ptr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);if (ptr == MAP_FAILED){perror("mmap");exit(0);}// 父子进程间通信int pid = fork();if (pid > 0){strcpy((char *)ptr, "hello world");wait(NULL);}else if (0 == pid){sleep(1);printf("%s\n", (char *)ptr);}// 释放内存映射区int ret = munmap(ptr, len);// int fd = open("englsih.txt", O_RDONLY);// // 获取原始文件的大小// int len = lseek(fd, 0, SEEK_END);// // 创建一个新文件,并对其大小进行拓展// int fd1 = open("cpy.txt", O_CREAT | O_RDWR, 0664);// truncate("cpy.txt", len);// write(fd1, " ", 1);// // 分别进行内存映射// void *ptr = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);// void *ptr1 = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0);// if (ptr == MAP_FAILED)// {// perror("mmap");// exit(0);// }// if (ptr1 == MAP_FAILED)// {// perror("mmap");// exit(0);// }// // 内存拷贝// memcpy(ptr1, ptr, len);// munmap(ptr1, len);// munmap(ptr, len);// close(fd1);// close(fd);return 0;
}
*/
C语言 sigchild回收子进程相关推荐
- Linux进程全解7——父进程wait / waitip回收子进程
以下内容源于朱有鹏<物联网大讲堂>的课程学习整理,如有侵权,请告知删除. 一.wait介绍 1.wait的工作原理 (1)子进程结束时,系统向其父进程发送SIGCHILD信号: (2)父进 ...
- Linux学习日记15——exec函数族、回收子进程
学习视频链接 黑马程序员-Linux系统编程_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1KE411q7ee?p=95&spm_id_from ...
- Linux学习之系统编程篇:利用 SIGCHLD 回收子进程
子进程死亡会给父进程发送 SIGCHLD 信号!(默认动作:父进程忽略该信号)此时父进程就可以捕捉该信号,利用回调函数使用 waitpid 回收子进程. #include <stdio.h> ...
- Linux系统编程--3(exec 函数族,僵尸进程和孤儿进程,wait和wait_pid回收子进程)
exec 函数族 fork 创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支) ,子进程往往要调用一种 exec 函数以执行另一个程序.当进程调用一种 exec 函数时,该进程的用户 ...
- Linux系统【三】回收子进程
孤儿进程 父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为init进程,则称init进程领养孤儿进程.现在好像是用户进程中的system进程. 僵尸进程 进程终止,父进程不进行回收,自己 ...
- linux基础知识——wait函数和waitpid函数回收子进程
1.wait函数回收子进程 \qquad父进程可以调用wait()函数回收子进程的终止信息.wait函数有三个功能: \qquad阻塞等待子进程退出 \qquad回收子进程残留资源 \qquad获取子 ...
- 进程之 回收子进程之避免僵尸进程的产生
wait() 与 waitpid() 函数的使用. 因为前段时间博主没有把Windows系统带走所以不能实时更新博客,请见谅.接下来就让我们继续开始进程的世界吧. 前面我们说到了如何创建多个子进程那么 ...
- go语言垃圾回收机制详解
Golang GC 垃圾回收机制详解 独一无二的小个性 https://blog.csdn.net/u010649766/article/details/80582153 摘要 在实际使用 go 语言 ...
- linux系统编程学习_(2)进程控制-- fork函数、exec函数族、回收子进程--孤儿进程僵尸进程、wait函数
linux系统编程学习_(2)进程控制-- fork函数.exec函数族.回收子进程–孤儿进程僵尸进程.wait函数 进程控制 fork()函数 创建一个子进程. pid_t fork(void); ...
最新文章
- RDKit | 化合物活性数据的不平衡学习
- 2018 俄罗斯世界杯赛程时间表
- matlab将图片转换为灰度图_视频处理之灰度图
- Embedding external files using [Embed] (转载:学习如何嵌入外部文件)
- c或c++语言什么时候用补码来运算,C/C++(基础编码-补码详解)
- PageLayoutControl的基本操作
- URL 路径长度限制(错误:指定的文件或文件夹名称太长)
- vue项目安装less_部署vue项目、安装mongodb
- 经典的 div + css 鼠标 hover 下拉菜单
- 数据 3 分钟 | 国产数据库迎来 2 名开源玩家、数据库厂商年度报告都说了些什么?...
- 泰勒公式在近似计算中的应用
- 【计算机网络】一篇文章带你分清波特率和比特率~
- [论文阅读笔记29]生物医学文本摘要(Biomedical Text Summarization)
- 钱晓捷第五版习题4 题4.8 bufx bufy bufz 为三个有符号十六进制数编写一个比较相等关系的程序如果这三个数都不相等则显示0,其中两个相等显示1 ,三个都相等则显示2
- 计算机主板扩展槽,计算机内部所有插槽介绍,10分钟读懂电脑主板,高手必备!...
- 天使、A轮、B轮……公司不同阶段估值方法大全
- 【USACO】2007 Feb Silver Lilypad Pond 白银莲花池
- mac pro 2015 升级1T固态硬盘极简版本(三星970 evo plus)
- 参考文献意译翻译借鉴
- 二维码:关于QR code的版权问题
热门文章
- 【报告分享】2021民宿行业数据报告-云掌柜(附下载)
- 索尼美能达50微-版本区别及实拍测评(sony/minolta)50 f2.8 macro
- 每天上下班之前读一遍,直到铭记在心……
- Testbench编写指南(2)文件的读写操作
- iphone ios 视频采集AVCaptureSessionPresetHigh/Medium/Low分辨率等参数
- 膜拜,阿里内部都在学习的五大深入理解Java虚拟机PDF,简直强无敌
- 锐龙r9 5900hx和i7 11800h哪个好 i711800h和锐龙r95900hx对比
- 【java】黑白图像
- 化工厂在岗人员定位系统-化工厂人员定位-化工厂定位-新导智能
- vue鼠标悬浮显示文字