Linux系统编程 day9 SIGCHLD and 线程

SIGCHLD信号

只要子进程信号发生改变,就会产生SIGCHLD信号。

借助SIGCHLD信号回收子进程

回收子进程只跟父进程有关。如果不使用循环回收多个子进程,会产生多个僵尸进程,原因是因为这个信号不会循环等待。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
#include<sys/wait.h>
#include<signal.h>void catch_child(int signo) //有子进程终止,发送sigchld信号时,该函数会被内核回调
{pid_t wpid;int status;//while((wpid = wait(NULL))!= -1);while((wpid = waitpid(-1 , &status , 0))!= 0 ){if(WISEXITED(status))printf("catch child:%d , status: %d\n" ,wpid , WEXITSTATUS(status));}
}int main(int argc , char *argv[])
{pid_t pid;int i ;//阻塞sigset_t set ;  // 防止在父进程创建sa_mask之前子进程先死亡。sigemptyset(&set);sigaddset(&set , SIGCHLD);sigprocmask(SIG_BLOCK , &set , NULL);for(i = 0 ; i < 5 ; i++){if((pid = fork()) == 0)break;}if(i == 5){struct sigaction act;act.sa_handler = catch_child;sigemptyset(&act.sa_mask);act.sa_flags = 0;sigaction(SIGCHLD , &act , NULL);//解除阻塞sigprocmask(SIG_UNBLOCK , &set , NULL);printf("I am parent , %d\n" , getpid());}else{printf("I am child , %d\n" , getpid());}return 0 ;
}

中断系统调用(非重点)

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

慢速系统调用:可能会使进程永远阻塞的一类。eg. read write wait and so on .

其他系统调用:getpid()....

sa_flags 用来设置被信号中断后系统调用是否重启。

进程组和会话

进程组也称之为作业。

创建会话

会话是多个进程组的集合。

注意事项

创建会话不能是进程组组长,该进程变成新会话首进程。

创建新会话丢弃原有的控制终端,该会话没有控制终端。

建立新会话时,先调用fork,父进程终止,子进程调用setsid()

getsid函数

获取进程所属的会话id

pid_t getsid(pid_t pid);
成功 返回会话id
失败 -1
ps ajx命令查看系统中的进程

组长进程不能成为新会话首进程,新会话首进程必定会成为组长进程。 

setsid函数

创建会话,以自己的ID设置进程组ID,同时也是新会话的ID

pid_t setsid(void)
成功:返回调用进程的会话id;
失败:-1

调用setsid函数的进程,既是新的会长,也是新的组长。

守护进程(daemon精灵,进程)

守护进程时Linux中的后台服务进程,通常运行与操作系统后台,脱离控制终端,一般不与用户直接交互 , 周期性的等待某个事件发生或周期性执行某一动作,不受用户登入注销影响。一般使用d结尾的名字。

守护进程创建步骤:

1、fork子进程,让父进程终止。

2、子进程调用setsid创建新会话。

3、通常根据需要,改变工作目录位置,chdir() , 防止目录被卸载

4、通常根据需要,重设置umask文件权限掩码,影响新文件的创建权限

5、通常根据需要,关闭/重定向 文件描述符

6、守护进程 业务逻辑 while()

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(int argc , char *argv[])
{pid_t pid ;int fd ;pid = fork();if(pid > 0){exit(0);   //正常终止父进程}else{pid = setsid();    //创建新会话if(pid == -1){perror("set error");exit(1);}int ret = chdir("/home/qqq");   //改变工作目录位置if(ret == -1){perror("chdir error");exit(1);}umask(0022);   // 设置掩码权限close(STDIN_FILENO);   // 关闭文件描述符fd = open ("/dev/null" , O_RDWR);if(fd == -1){perror("open error");exit(1);}dup2(fd , STDOUT_FILENO);   //重定向dup2(fd , STDERR_FILENO);while(1);  // 模拟守护进程做的事情}return 0 ;
}

这里由于我不明白为什么需要将标准输入关闭,并且将标准输出和标准错误重定向,我上网查了一些资料:

1、为什么要关闭STDIN_FILENO?
守护进程是在后台运行的,不应该与终端交互,因此不需要标准输入,为防止错误,直接关闭。

2、为什么要将STDOUT and STDERR   --->fd 0  ("/dev/null")

"/dev/null"是一个特殊设备,写的什么东西进去都会被吃掉,读取的时候什么也看不到,守护进程不应该输出信息到终端,因此重定向给 fd(此时是 /dev/null)本质上就是为了干净、不占资源、避免潜在错误。

线程(不要将线程和信号混合用)

线程 : LWP,light weight process 轻量级的进程 , 本质仍是进程(Linux环境下)

进程: 独立的进程地址空间 , 有PCB

线程:有独立的PCB,但没有独立的地址空间(共享)

Linux下 线程是最小的执行单位 , 进程是最小分配资源单位,可以看成只有一个线程的进程。

ps -Lf 进程id  --->线程号 LWP --->CPU执行的最小单位。

线程可以看作寄存器和栈的集合。

线程共享资源

文件描述符表 、 每种信号的处理方式 、 当前工作目录 、 用户ID和组ID 、 内存地址空间、全局变量

线程非共享资源

线程id 、 处理器现场和栈指针(内核栈) 、独立的栈空间(用户栈) 、 error变量 、 信号屏蔽字

线程的优缺点

优点:提高程序的并发性 , 开销小 , 数据通信、共享数据方便

缺点:库函数不稳定 , 调试、编写困难、GDB不支持 , 对信号支持不友好

优点突出,缺点不明显,能使用线程使用线程

线程控制原语

pthread_self函数

获取线程ID ,注意这里的线程ID和线程号LWP不一样。

线程id是在进程地址空间内部,用来表示线程身份id号

pthread_t pthread_self(void);
成功返回 线程id

pthread_create函数

int pthread_create(pthread_t * tid ,const pthread_attr_t *attr , void *(*start_rountn)(void*) , void *arg);pthread_t * tid:传出参数,传出创建子线程的id。
const pthread_attr_t *attr:线程属性 , 传NULL表示使用默认属性。
void *(*start_rountn)(void*):子线程回调函数,创建成功,pthread_create()函数返回时,该回调函数                            会被自动调用。
void *arg:回调函数的参数,没有的话使用NULL返回值 成功 0
失败errno

循环创建5个子线程。 

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>void* func(void * arg)
{int i = (int) arg;printf("I am %dth child , pid:%d , tid:%lu\n" , i+1 , getpid() , pthread_self());return NULL;    
}int main(int argc , char* argv[])
{pthread_t tid;int i ,ret;for(i = 0 ; i < 5 ; i++){ret = pthread_create(&tid , NULL , func , (void*)i);if(ret == -1){perror("pthread_create error");exit(1);}    }sleep(i);printf("I am main , pid:%d , tid:%lu\n" , getpid() , pthread_self());return 0 ;    
}

pthread_exit函数

将当前线程退出。

void pthread_exit(void *retval);
retval:退出值。无退出值时,NULLexit() ; 退出当前进程
return ; 返回到调用者那里去
pthread_exit() ; 将调用该函数的线程退出

pthread_join函数

阻塞等待线程退出,获取线程退出状态。回收子线程。

int pthread_join(pthread_t thread, void **retval);
返回值 成功 0 
失败 -1

pthread_cancel函数

杀死(取消)线程。相当于kill函数。但是需要取消点(保存点) 。如果子线程没有到达取消点,那么该函数无效,我们可以在程序中手动添加一个取消点,使用pthread_testcancel()。成功被cancel函数杀死的进程,可以使用pthread_join回收。

int pthread_cancel(pthread_t thread);
返回值: 成功 0 
失败 errno

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

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

相关文章

微信小程序拖拽排序有效果图

效果图 .wxml <view class"container" style"--w:{{w}}px;" wx:if"{{location.length}}"><view class"container-item" wx:for"{{list}}" wx:key"index" data-index"{{index}}"style"--…

hadoop三大组件的结构及各自的作用

1 HDFS 1.1功能 HDFS 是 Hadoop 的分布式文件系统&#xff0c;用于存储和管理海量数据。它具有高容错性、高吞吐量和可扩展性&#xff0c;能够在多个节点上存储和管理大规模数据 1.2架构&#xff1a;采用主从架构&#xff0c;由一个 NameNode 和多个 DataNode 组成。NameNode…

解决jupyter notebook修改路径下没有c.NotebookApp.notebook_dir【建议收藏】

文章目录 一、检查并解决问题二、重新设置默认路径创作不易&#xff0c;感谢未来首富们的支持与关注&#xff01; 最近在用jupyter notebook编写代码时&#xff0c;更新了一下Scikit-learn的版本&#xff0c;然后重新打开jupyter notebook的时候&#xff0c;我傻眼了&#xff0…

MCP Host、MCP Client、MCP Server全流程实战

目录 准备工作 MCP Server 实现 调试工作 MCP Client 实现 MCP Host 配置 第一步:配置支持 function calling的 LLM 第二步:添加MCP Server 一般有两种方式,第一种json配置,第二种直接是Command形式,我这里采用Command形式 第三步:使用MCP Server 准备工作 安装…

4.21—4.22学习总结 JavaWeb:HTML-CSS

Web&#xff1a;能够通过浏览器访问到的网站。 Web标准&#xff1a; HTML&#xff1a; vscode中进行注释的快捷键为ctrl斜线/ h1的字体最大&#xff0c;依次递减&#xff0c;只存在h1—h6。 超链接&#xff1a; 设置字体颜色&#xff1a; 方式三写一个css文件&#xff0c;将方…

Kaamel Agent: 基于EU AI Act的AI影响评估(AIIA)

1. 引言&#xff1a;安全视角下的AI监管 随着人工智能技术的快速发展和广泛应用&#xff0c;AI系统在为社会带来创新和效率的同时&#xff0c;也引发了诸多关于安全、隐私和合规的担忧。在这一背景下&#xff0c;全球范围内涌现出多种监管框架和标准&#xff0c;旨在确保AI系统…

Mongodb分布式文件存储数据库

文章目录 一、MongoDB 简介基本信息特点内部组件 二、MongoDB 部署1. 安装依赖2. 解压部署并配置环境变量3. 修改配置文件以及启动服务4.数据库权限管理 三、MongoDB 管理1. 角色权限2. 操作命令用户管理命令常用命令&#xff08;Mongo4.2.8&#xff09;数据库相关用户相关集合…

麒麟V10安装MySQL8.4

1、下载安装包 wget https://cdn.mysql.com//Downloads/MySQL-8.4/mysql-8.4.5-1.el7.x86_64.rpm-bundle.tar2、解压 mkdir -p /opt/mysql tar -xvf mysql-8.4.5-1.el7.x86_64.rpm-bundle.tar -C /opt/mysql3、安装MySQL 3.1、卸载mariadb rpm -qa | grep mariadb rpm -e m…

Unreal如何使用后处理材质实现一个黑屏渐变效果

文章目录 前言相机后期处理材质创建材质相机设置动态修改FadeAlpha参数使用示例最后前言 UE5 开发VR ,如何通过PostProcess轻松实现黑屏渐变效果 最简单的办法,其实是使用一个半球形模型,遮挡住相机,然后控制这个半球形遮罩的颜色透明度,至少Unity中默认的Tunneling是这么…

其它生成式(对比列表生成式)

一、字典生成式&#xff1a; # keys[name, age, gender] # dic{key:None for key in keys} # print(dic) items[(name, Tom), (age, 18), (gender, male)] res{k:v for k,v in items if k ! gender} print(res) 二、集合生成式&#xff1a; keys[name, age, gender] set1{ke…

健身房管理系统(springboot+ssm+vue+mysql)含运行文档

健身房管理系统(springbootssmvuemysql)含运行文档 健身房管理系统是一个全面的解决方案&#xff0c;旨在帮助健身房高效管理其运营。系统提供多种功能模块&#xff0c;包括会员管理、员工管理、会员卡管理、教练信息管理、解聘管理、健身项目管理、指导项目管理、健身器材管理…

LeetCode 第 262 题全解析:从 SQL 到 Swift 的数据分析实战

文章目录 摘要描述题解答案&#xff08;SQL&#xff09;Swift 题解代码分析代码示例&#xff08;可运行 Demo&#xff09;示例测试及结果时间复杂度分析空间复杂度分析总结未来展望 摘要 在实际业务中&#xff0c;打车平台要监控行程的取消率&#xff0c;及时识别服务质量的问…

三生原理与现有密码学的核心区别?

AI辅助创作&#xff1a; 三生原理与现有密码学的核心区别 一、‌哲学基础与设计逻辑‌ ‌动态生成 vs 静态分析‌ 三生原理以“阴阳动态平衡”为核心&#xff0c;通过参数化生成&#xff08;如素数构造中的阴阳元联动公式&#xff09;模拟系统演化过程&#xff0c;而现有密码…

4.19-4.20学习总结 网络编程+反射+动态代理

网络编程&#xff1a; IPv6有2的128次方个ip。 端口号&#xff1a; 协议&#xff1a; UDP发送和接收消息&#xff1a; UDP的三种通信方式&#xff1a; 单播&#xff1a;一对一&#xff0c;一个发送端对应一个接收端 创建DatagramSocket对象 组播&#xff1a;一个发送端对应一…

Swiper、样式结构重用、GridGridItem

今日核心&#xff1a; 容器组件&#xff1a;Swiper、Grid\GridItem样式&结构重用&#xff1a;Builder、Extend、Styles 相关资源: 图片素材&#xff1a;&#x1f4ce;day01.zip 1. Swiper 1.1. 适用场景 首先来看看 Swiper 在什么情况下会用到 链接 Swiper组件提供滑…

前沿分享|技术雷达202504月刊精华

本期雷达 ###技术部分 7. GraphRAG 试验 在上次关于 检索增强生成&#xff08;RAG&#xff09;的更新中&#xff0c;我们已经介绍了GraphRAG。它最初在微软的文章中被描述为一个两步的流程&#xff1a; &#xff08;1&#xff09;对文档进行分块&#xff0c;并使用基于大语言…

数据结构与算法-顺序表应用

一.通讯录的创建 首先我们要理解的是通讯录本身就是以顺序表为底层的 只不过顺序表中的数组&#xff0c;这里我们是用结构体来替代&#xff0c;用来存储用户的信息 由于是通讯录的本质就是顺序表&#xff0c;所以顺序表的任何方法它都能套用 Contact.h: #pragma once #def…

【C++】新手入门指南(下)

文章目录 前言 一、引用 1.引用的概念和定义 2.引用的特性 3.引用的使用 4.const引用 5.指针和引用的关系 二、内联函数 三、nullptr 总结 前言 这篇续上篇的内容新手入门指南&#xff08;上&#xff09;&#xff0c;继续带大家学习新知识。如果你感兴趣欢迎订购本专栏。 一、…

uniapp-商城-33-shop 布局搜索页面以及u-search

shop页面上有一个搜索&#xff0c;可以进行商品搜索&#xff0c;这里我们先做一个页面布局&#xff0c;后面再来进行数据i联动。 1、shop页面的搜索 2、搜索的页面代码 <navigator class"searchView" url"/pagesub/pageshop/search/search"> …

SAP 采购订单如何防止开票数量 大于 收货数量呢

配置点如下&#xff1a; 事务码&#xff1a;OMRM&#xff0c;配置如下 当过账开票的数量 大于收货数量的时候会提示如下&#xff1a;