进程间通信(二)

news2024/11/17 4:32:11

共享内存

当进程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 -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) 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.coloradmin.cn/o/1664693.html

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

相关文章

【数组算法】598. 区间加法

给你一个 m x n 的矩阵 M 和一个操作数组 op 。矩阵初始化时所有的单元格都为 0 。ops[i] [ai, bi] 意味着当所有的 0 < x < ai 和 0 < y < bi 时&#xff0c; M[x][y] 应该加 1。 在 执行完所有操作后 &#xff0c;计算并返回 矩阵中最大整数的个数 。 示例 1: …

户籍管理系统的设计与实现

【免费】户籍管理系统的设计与实现.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89296790 ​​​​​​​户籍管理系统的设计与实现 摘 要 当今社会人们生活质量越来越高&#xff0c;人们对生活品质的追求不断提升&#xff0c;对于孩子求学&#xff0c;变更住…

内容安全(AV)

防病毒网关&#xff08;AV&#xff09;简介 基于网络侧 识别 病毒文件&#xff0c;工作范围2~7层。这里的网关指的是内网和外网之间的一个关口&#xff0c;在此进行病毒的查杀。在深信服中就有一个EDR设备&#xff0c;该设备就是有两种部署&#xff0c;一个部署在网关&#xf…

C# WinForm —— 15 DateTimePicker 介绍

1. 简介 2. 常用属性 属性解释(Name)控件ID&#xff0c;在代码里引用的时候会用到,一般以 dtp 开头Format设置显示时间的格式&#xff0c;包含Long&#xff1a; Short&#xff1a; Time&#xff1a; Custom&#xff1a;采用标准的时间格式 还是 自定义的格式CustomFormat自定…

关于 vs2019 c++ 20规范,STL 库提供的标准分配器 alloctor 及其 traits 及涉及分配器交换的全局函数 _Pocs

(1) 我们写 c 代码&#xff0c;使用 STL 库中的模板&#xff0c;很少自己写对象的分配器。用 STL 中的分配器也够用。研究 STL 中的分配器也可以为咱们自己写分配器提供参考。 咱们会遇到这样的场景&#xff0c;例如交换两个容器对象&#xff1a; list a ,b ; a .swap (b) ; 这…

搭建一个Xx431?

搭建一个Xx431? 嘿uu们!刚结束了一周六天班感觉如何? 我的状态倒还行,工作生活总能找到乐子,本周整活就是用纸巾和蛋糕托做的油灯,另外想制冷片做个温水冷水可调的杯托,但我还不会搞3d,希望今年能搞起来. 题外话就说到这,这个选题也是因为实际遇到的问题需要这玩意,下班路…

初识java--javaSE(3)--方法,递归,数组,

文章目录 一 方法的使用1.1 什么是方法&#xff1f;main方法注意事项 1.2 方法的调用嵌套调用在方法调用时形参与实参的关系&#xff1a; 1.3 方法的重载方法重载的意义&#xff1f;总结方法重载&#xff1a;方法签名&#xff1a; 二 递归什么是递归&#xff1f;递归的精髓&…

做题杂记666

[XYCTF2024] 铜匠 题目描述&#xff1a; from Crypto.Util.number import * from secrets import flagm bytes_to_long(flag) m1 getRandomRange(1, m) m2 getRandomRange(1, m) m3 m - m1 - m2def task1():e 149p getPrime(512)q getPrime(512)n p * qd inverse(e,…

C++11:并发新纪元 —— 深入理解异步编程的力量(1)

hello &#xff01;大家好呀&#xff01; 欢迎大家来到我的Linux高性能服务器编程系列之《C11&#xff1a;并发新纪元 —— 深入理解异步编程的力量》&#xff0c;在这篇文章中&#xff0c;你将会学习到C新特性以及异步编程的好处&#xff0c;以及其如何带来的高性能的魅力&…

【学习笔记】HarmonyOS 4.0 鸿蒙Next 应用开发--安装开发环境

开发前的准备 首先先到官网去下载Devco Studio 这个开发工具&#xff0c;https://developer.harmonyos.com/cn/develop/deveco-studio/#download 提供了WIndows和Mac的开发环境&#xff0c;我自己是Windows的开发环境。 所以下载之后直接点击exe进行安装即可。 如果之前安装过…

nc生成临时凭证配置

nc生成临时凭证配置 要实现的功能&#xff1a; 审批时生成临时凭证弃审时删除临时凭证 前台配置 后台配置 BillReflectorServiceImpl.java package nc.pubimpl.jych.qtsq.voucher;import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; impo…

vue3专栏项目 -- 三、使用vue-router 和 vuex(下)

一、添加columnDetail 页面 首页有专栏列表&#xff08;ColumnList组件&#xff09;&#xff0c;专栏列表中有很多专栏&#xff0c;然后点击某个专栏就进入专栏详情页&#xff08;ColumnDetail组件&#xff09;&#xff0c;专栏详情页中有很多文章&#xff0c;点击某个文章就进…

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

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

VTK官方示例

VTK官方示例 -vtk字體 #!/usr/bin/env python# noinspection PyUnresolvedReferences import vtkmodules.vtkInteractionStyle # noinspection PyUnresolvedReferences import vtkmodules.vtkRenderingFreeType # noinspection PyUnresolvedReferences import vtkmodules.vtk…

创新指南 |风险管理:企业如何应对颠覆性创新带来的挑战

在当今充满变数的商业时代&#xff0c;颠覆性创新是企业突破传统、引领市场的关键。然而&#xff0c;真正的创新之旅并不平坦&#xff0c;充满了挑战和不确定性。文章将快速引导读者了解颠覆性创新的定义、挑战、以及如何通过设计思维、市场洞察、利益相关者沟通和文化变革等关…

专业数字音频编码器 JR-AE401

简介 JR-AE401专业模拟&数字音频编码器采用最为先进的MPEG4 AAC音频压缩算法&#xff0c;在低网络带宽的严酷条件下也具备优异的音频还原性。支持多种音频编码标准&#xff0c;例如AAC-LC,AAC-HE,AAC-HEv2等。 为适应各种复杂的网络音频应用环境JR-AE401提供了丰富的流媒…

数据结构十三:八大排序算法

排序算法&#xff08;sorting algorithm&#xff09;是用于对一组数据按照特定顺序进行排列。排序算法有着广泛的应用&#xff0c;因为有序数据通常能够被更高效地查找、分析和处理。排序算法中的数据类型可以是整数、浮点数、字符或字符串等。排序的判断规则可根据需求设定&am…

串口属性中的BM延时计时器问题

如果使用程序修改则需要修改注册表对应位置如下 第一个示例&#xff08;217&#xff09; 第二个示例&#xff08;219&#xff09; 需要注意的事情是修改前必须点查看串口名称&#xff08;例如上图是com5&#xff09; 程序修改&#xff1a; 有没有办法以编程方式更改USB <…

算法设计与分析 例题解答 解空间与搜索

1.请画出用回溯法解n3的0-1背包问题的解空间树和当三个物品的重量为{20, 15, 10}&#xff0c;价值为{20, 30, 25}&#xff0c;背包容量为25时搜索空间树。 答&#xff1a; 解空间树&#xff1a; 搜索空间树&#xff1a; 2. 考虑用分支限界解0-1背包问题 给定n种物品和一背包…