进程间通信(二)

共享内存

当进程A和进程B有一块共享的内存空间时,这两个进程之间的数据交互就会变的很简单,只需要像读取自己内存空间中的元素一样去读取数据即可。实现共享内存进行数据交互的一般步骤:

  1. 创建/打开共享内存
  2. 内存映射
  3. 数据交换
  4. 断开与共享内存的连接
  5. 清除共享内存

相关api

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>//创建或获取一个共享内存:成功返回共享内存ID,失败返回-1
int shmget(key_t key, size_t size, int shmflg);
//连接共享内存到当前进程的地址空间:成功返回指向共享内存的指针,失败返回-1
void *shmat(int shmid, const void *shmaddr, int shmflg);
//断开与共享内存的连接:成功返回0,失败返回-1
int shmdt(const void *shmaddr);
//控制共享内存的相关信息:成功返回0,失败返回-1
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

共享内存实现数据通信:
shmw.c:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>int main(){int shmid;char *shmaddr;key_t key;key = ftok(".",1);shmid = shmget(key,1024*4,IPC_CREAT|0666);if(shmid == -1){printf("create share memory fail\n");}shmaddr = shmat(shmid,0,0);//第二个0是让系统自动分配空间,第三个0是默认可读可写printf("shmat ok!\n");strcpy(shmaddr,"hello world!");sleep(5);shmdt(shmaddr);shmctl(shmid,IPC_RMID,0);printf("quit!\n");return 0;
}

shmr.c:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>int main(){int shmid;char *shmaddr;key_t key;key = ftok(".",1);shmid = shmget(key,1024*4,0);   //0代表正常获取共享内存if(shmid == -1){printf("create share memory fail\n");}shmaddr = shmat(shmid,0,0);//第二个0是让系统自动分配空间,第三个0是默认可读可写printf("read data from w:%s\n",shmaddr);shmdt(shmaddr);printf("quit!\n");return 0;
}

gcc shmw.c -o w;
gcc shmr.c -o r;
现在一个终端执行./w在另一个终端执行./r执行结果为为:
./w
shmat ok!
quit!
./r
read data from w:hello world!
quit!
另外我们可以利用ipcs -m指令查看当前系统中的共享内存。
共享内存也存在缺点,当进程A和进程B使用共享内存进行通信时,可能会出现这样一种情况:进程A和B同时向共享内存中写数据,可能会导致数据出现错乱。即共享内存不能实现原子操作,这种情况需要借助信号量来进行解决。

linux信号概述

对于linux来说,实际信号是软中断,许多重要的程序需要处理信号。信号,为linux提供了一种处理异步事件的方法。比如,终端用户输入了ctrl+c来终端程序,会通过信号机制停止一个程序。可以通过kill -l来查看系统中的信号

信号类型

kill -l1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX	

信号处理

对于信号我们可以采取三种方式来进行处理:忽略、捕捉和默认动作。

忽略信号

大多数信号可以使用这个方式来处理,但是有两种信号不能被忽略(分别是SIGKILL和SIGSTOP)。

捕捉信号

可以写一个信号处理函数,然后把这个函数告诉内核,当该信号产生时,由内核来调用用户自定义的函数,一次来实现某种信号的处理。

系统默认动作

对于每个信号来说,系统都对应有默认的处理动作,当发生了该信号,系统会自动执行。

最简单的一个信号,当我们执行一个死循环时,我们可以直接利用kill -SIGKILL pid号来杀死该进程:

#include <stdio.h>
int main(){while(1);return 0;
}

运行这代断码会一直处理死循环,此时我们先利用 ps -aux|grep a.out来查看该进程的pid号,之后利用kill -9 pid或kill -SIGKILL pid来杀死该进程:
./a.out
Killed

信号变成

*#include <signal.h>
typedef void (sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

signum:就是选择上面的64种信号类型。handler是个函数指针,指明了遇到signum这种类型的信号将作何处理。
正常来说像我们上面的代码遇到while(1)卡死循环的情况我们可以用ctrl+C来终止进程,这是系统的默认动作,当然我们也可以捕捉信号,自己写一个handler函数来改变默认的行为:

#include <stdio.h>
#include <signal.h>void handler(int signum){printf("signum=%d\n",signum);printf("never quit!\n");
}int main(){signal(SIGINT,handler);while(1);return 0;
}

运行结果:
./a.out

^Csignum=2
never quit!
^Csignum=2
never quit!
^Csignum=2
never quit!
^Csignum=2
never quit!
^Csignum=2
never quit!

我们无法用ctrl+c来终止这个死循环进程。可以用kill -9 +pid来杀死进程。
同时我们也可以通过参数的方式利用代码来杀死进程:

#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <signal.h>int main(int argc,char **argv){int pid;int signum;signum = atoi(argv[1]);pid = atoi(argv[2]);printf("signum=%d,pid=%d\n",signum,pid);kill(pid,signum);printf("send signal ok!\n");return 0;
}

将这段代码编译为可执行程序,gcc signal1Ctl.c -o myKill;
首先运行./a.out就是上面那个死循环函数,直接在另一个终端查询该进程的pid号,然后运行./myKill 9 pid来杀死进程
在这里插入图片描述
除了利用kill来完成上述操作,我们也可以利用system来调用脚本:

#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <signal.h>int main(int argc,char *argv[]){int pid;int signum;char cmd[128];signum = atoi(argv[1]);pid = atoi(argv[2]);printf("signum=%d,pid=%d\n",signum,pid);//kill(pid,signum);sprintf(cmd,"kill -%d %d",signum,pid);//cmd="kill signum pid"system(cmd);printf("send signal ok!\n");return 0;
}

一样可以实现上述效果。

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

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

相关文章

任务:单域,域树的搭建

一、单域&#xff1a; 搭建所需的系统&#xff1a;win2016 sever&#xff0c;win10 1.在创建域前&#xff0c;先设置静态ip 先查看win2016 sever的IP&#xff0c; ip&#xff1a;192.168.154.133 网关&#xff1a;192.168.154.2 DNS服务器&#xff1a;192.168.154.2 设置…

【nodejs 命令行交互神器 - inquirer.js】

需求 大家在开发时&#xff0c;有时需要从命令行读取用户的输入&#xff0c;或者让用户选择。在nodejs中&#xff0c;这个怎么实现? 原生实现 ❌ process.stdin.setEncoding(utf8);process.stdin.on(readable, () > {let chunk;// 使用循环确保我们读取所有的可用输入wh…

局域网内监控软件有哪些:五款好用的网络监控神器分享

面对员工这种现象怎么办&#xff1f; 监控电脑最有效&#xff01; 局域网监控软件&#xff0c;你值得拥有&#xff01; 要想轻松监控电脑&#xff0c;这几款局域网内监控软件不容错过&#xff01;&#xff01;&#xff01; 一、域智盾软件 是一款专注于企业终端安全管理的软…

中职大数据专业介绍:大数据技术应用

近年来&#xff0c;人工智能在经济发展、社会进步、国际政治经济格局等方面已经产生重大而深远的影响。规划纲要对“十四五”及未来十余年我国人工智能的发展目标、核心技术突破、智能化转型与应用&#xff0c;以及保障措施等多个方面都作出了部署。 据2020年全国教育事业发展统…

两重惊喜!奥特曼预告GPT-4和ChatGPT重大更新,Open AI要放大招

OpenAI在今天官宣13日&#xff08;下周一10点&#xff09;开启线上直播&#xff0c;将会展示全新的ChatGPT demo的演示以及GPT-4的重大更新&#xff01; OpenAI首席执行官Sam Altman在X上表示&#xff0c;这些的发布会&#xff0c;公司不会宣布下一代对话式人工智能GPT-5或人工…

ue引擎游戏开发笔记(37)——实现造成伤害

1.需求分析&#xff1a; 在游戏中已经能够射击&#xff0c;并且能得到实际的落点反馈&#xff0c;但本质上这种射击没有任何实际数值伤害&#xff0c;为射击添加实际的子弹伤害数值。 2.操作实现&#xff1a; 1.思路&#xff1a;ue本身函数FPointDamageEvent就可以解决&#x…

win11安装各银行的网银助手都无法打开,双击没反应?

大神贴 右键网银助手属性&#xff0c;在目标后面敲一下空格&#xff0c;输入**-runapp**&#xff0c;应用即可。 如图示例&#xff1a;

【HDFS】关于HDFS-17497:在commit block时更新quota

链接:https://github.com/apache/hadoop/pull/6765 Ticket标题:The number of bytes of the last committed block should be calculated into the file length。 HDFS里,一个在写入的文件可能包含多个commited状态的块。 但是计算文件大小的时候,最后一个commited block并…

Vue3人员选择组件封装

一、组件介绍 人员组件在各系统的应用都是比较广泛的&#xff0c;因此可以将其封装为可配置的人员组件&#xff0c;根据不同角色权限显示对应的人员供选择&#xff0c;代码目前只是一部分&#xff0c;需要源码的私聊。 二、直接上代码 use.vue 父组件 <div class&q…

BUU-[极客大挑战 2019]Http

考察点 信息收集 http构造请求数据包 题目 解题步骤 参考文章&#xff1a;https://zhuanlan.zhihu.com/p/367051798 查看源代码 发现有一个a标签&#xff0c;但是οnclick"return false"就是点击后不会去跳转到Secret.php的页面 所以我就自己拼接url http://no…

音频—WAV格式及写入wav文件代码实现

1.RIFF规范 FIFF 是 Resource Interchange File Format&#xff08;资源交换文件格式&#xff09;的简称。RIFF 是一种文件格式规范&#xff0c;用于在计算机系统之间交换和存储多媒体资源。WAV 文件格式是 Microsoft 的 RIFF 规范的一个子集。 RIFF 规则定义了文件的结构和数…

【案例分享】校园服务小程序开发经验和主要功能,引领校园生活新方式

随着移动互联网的普及&#xff0c;学生们对于校园生活的需求也在不断增长。校园圈子、校园跑腿、校园外卖、校园服务等小程序等应用应运而生&#xff0c;为学生们提供了更加便捷、高效的生活方式。那么&#xff0c;如何开发一款能够满足学生需求的校园服务小程序呢&#xff1f;…

JavaScript创建日期

创建日期 在JavaScript中创建日期有四种方法 ● 使用new Date() const now new Date(); console.log(now);● 直接输入月、日、年、时间 console.log(new Date(Aug 02 2024 18:05:41));● 也可以输入年月日 console.log(new Date(December 24, 2015));● 直接按照年、月、…

C++入门系列-析构函数

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 析构函数 概念 析构函数&#xff0c;与构造函数功能相反&#xff0c;析构函数不是完成对对象本身的销毁&#xff0c;局部对象销毁工作是由编译器完成的&#xff0c;而对象在销…

基于深度学习的人体关键点检测与姿态识别

文章目录 源码下载地址&#xff1a; 源码地址在视频简介中 深度学习人体关键点检测&#xff0c;姿态识别 界面效果&#xff1a; 界面代码&#xff1a; from PyQt5.QtGui import * from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * f…

OGG几何内核开发-BRepAlgoAPI_Fuse与BRep_Builder.MakeCompound比较

最近在与同事讨论BRepAlgoAPI_Fuse与BRep_Builder.MakeCompound有什么区别。 一、从直觉上来说&#xff0c;BRepAlgoAPI_Fuse会对两个实体相交处理&#xff0c;相交的部分会重新的生成相关的曲面。而BRep_Builder.MakeCompound仅仅是把两个实体组合成一个新的实体&#xff0c;…

Apache Sqoop:高效数据传输工具搭建与使用教程

目录 引言一、环境准备二、安装sqoop下载sqoop包解压文件 三、配置Sqoop下载mysql驱动拷贝hive的归档文件配置环境变量修改sqoop-env.sh配置文件替换版本的commons-lang的jar包 验证Sqoop安装查看Sqoop版本测试Sqoop连接MySQL数据库是否成功查看数据库查看数据表去除警告信息 四…

【免费】在线识别通用验证码接口

模块优势价格5元1000次&#xff0c;每天免费100次api文档支持 使用量小的完全够用了 <?phpfunction Post_base64($base64_str){$url http://api.95man.com:8888/api/Http/Recog?Taken41******QK&imgtype1&len0 ; $fields array( ImgBase64>$base64_str); $ch…

031.下一个排列Java实现

题意 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如&#xff0c;arr [1,2,3] &#xff0c;以下这些都可以视作 arr 的排列&#xff1a;[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地&#…

移除链表元素(C语言)———链表经典算法题

题目描述&#xff1a;203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09; 答案展示: 答1&#xff08;遍历删除&#xff09;&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNo…