进程间通信(二)

共享内存

当进程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.mfbz.cn/a/614910.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

icap对flash的在线升级

文章目录 一、icap原语介绍&#xff08;针对 S6 系列的 ICap&#xff09;&#xff0c;之后可以拓展到A7、K7当中去二、程序1设计2.1信号结构框图2.2 icap_delay设计2.3 icap_ctrl设计&#xff08;可以当模板使用&#xff0c;之后修改关键参数即可&#xff09; 三、程序2设计四、…

C++中调用python函数(VS2017+WIN10+Anaconda虚拟环境)

1.利用VS创建C空项目 step1 文件——新建——项目 step2 Visual C—— Windows桌面——Windows桌面向导 step3 选择空项目 step4 源文件——新建项——添加 step5 Visual C——C文件&#xff08;.cpp&#xff09; 2.配置环境 Step1. 更换成Release与X64 Step2. 打开项目属性&…

巨坑啊! before-upload返回false 会执行on-remove

通过对on-remove对应参数的打印&#xff0c;发现回调中的file参数有个status&#xff0c;若是是在before-upload中就被过滤了&#xff0c;就是ready&#xff0c;若是已经上传成功了去点击删除&#xff0c;status是success&#xff0c;就他了。 onRemove(file,fileList){if(file…

探索Linux:深入理解各种指令与用法

文章目录 cp指令mv指令cat指令more指令less指令head指令tail指令与时间相关的指令date指令 cal指令find指令grep指令zip/unzip指令总结 上一个Linux文章我们介绍了大部分指令&#xff0c;这节我们将继续介绍Linux的指令和用法。 cp指令 功能&#xff1a;复制文件或者目录 语法…

在 Python 的哪个版本之后,字典的添加顺序与键的顺序是一致的?

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 在 Python 的不同版本中&#xff0c;字典&#xff08;dict&#xff09;类型的行为发生了显著变化。在 Python 3.6 及之前的版本中&#xff0c;字典是无序的&#xff0c;这意味着字典在遍历时不能保证按…

图鸟模板-官网:基于Vue 3的前端开发新篇章

一、引言 随着前端技术的飞速发展&#xff0c;企业对于官网的需求也从简单的展示型网站向功能丰富、交互体验良好的方向转变。在这样的背景下&#xff0c;图鸟模板-官网以其基于Vue 3的纯前端开发特性&#xff0c;以及支持微信小程序、支付宝小程序、APP和H5的跨平台能力&…

【.NET Core】你认识Attribute之CallerMemberName、CallerFilePath、CallerLineNumber三兄弟

你认识Attribute之CallerMemberName、CallerFilePath、CallerLineNumber三兄弟 文章目录 你认识Attribute之CallerMemberName、CallerFilePath、CallerLineNumber三兄弟一、概述二、CallerMemberNameAttribute类三、CallerFilePathAttribute 类四、CallerLineNumberAttribute 类…

每个初创企业创始人都应了解的搜索引擎优化基础知识

会话式AI引擎&#xff1a;如何革新您的业务通讯&#xff1f; 对于已经身兼数职的初创企业创始人来说&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;似乎是一项艰巨的任务。然而&#xff0c;在数字时代&#xff0c;它是推动流量、建立品牌知名度和实现长期成功不可或缺的…

Golang编译优化——稀疏条件常量传播

文章目录 一、概述二、稀疏条件常量传播2.1 初始化worklist2.2 构建def-use链2.3 更新值的lattice2.4 传播constant值2.5 替换no-constant值 一、概述 常量传播&#xff08;constant propagation&#xff09;是一种转换&#xff0c;对于给定的关于某个变量 x x x和一个常量 c …

c++ 归并排序

归并排序是一种遵循分而治之方法的排序算法。它的工作原理是递归地将输入数组划分为较小的子数组并对这些子数组进行排序&#xff0c;然后将它们合并在一起以获得排序后的数组。 简单来说&#xff0c;归并排序的过程就是将数组分成两半&#xff0c;对每一半进行排序&#xff0c…

车辆运动模型中LQR代码实现

一、前言 最近看到关于架构和算法两者关系的一个描述&#xff0c;我觉得非常认同&#xff0c;分享给大家。 1、好架构起到两个作用&#xff1a;合理的分解功能、合理的适配算法&#xff1b; 2、好的架构是好的功能的必要条件&#xff0c;不是充分条件&#xff0c;一味追求架构…

贝壳面试:MySQL联合索引,最左匹配原则是什么?

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 1.谈谈你对MySQL联合索引的认识&#xff1f; 2.在MySQ…

【强训笔记】day20

NO.1 思路&#xff1a;先判断能对砍几个回合&#xff0c;取最小值&#xff0c;因为回合数是整数&#xff0c;所以可能存在都大于0的情况&#xff0c;再判断一下如果都存活就再对砍一次&#xff0c;直到一家存活或者都死亡。 代码实现&#xff1a; #include<iostream>u…

即插即用篇 | YOLOv8 引入多光谱通道注意力 | 频率领域中的通道注意力网络

本改进已集成到 YOLOv8-Magic 框架。 注意力机制,尤其是通道注意力,在计算机视觉领域取得了巨大成功。许多工作聚焦于如何设计高效的通道注意力机制,同时忽略了一个基本问题,即通道注意力机制使用标量来表示通道,这很困难,因为会造成大量信息的丢失。在这项工作中,我们从…

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

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

【一支射频电缆的诞生】GORE 戈尔

工具连接&#xff1a; https://microwave-cablebuilder.gore.com/ 控制参数&#xff1a; 连接器&#xff1a; 欣赏

Ubuntu18.04--虚拟机配置Samba并从Windows登录

前言&#xff1a; 本文记录我自己在Windows上安装 Virtualbox &#xff0c;并在Virtualbox中安装 Ubuntu-18.04 虚拟机&#xff0c;在Ubuntu-18.04虚拟机里安装配置Smaba服务器&#xff0c;从 Windows 宿主系统上访问虚拟机共享samba目录的配置命令。 引用: N/A 正文 虚拟…

《Python编程从入门到实践》day25

# 昨日知识点回顾 如何创建多行外星人 碰撞结束游戏 创建game_stats.py跟踪统计信息 # 今日知识点学习 第14章 记分 14.1 添加Play按钮 14.1.1 创建Button类 import pygame.font# button.py class Button:def __init__(self, ai_game, msg):"""初始化按钮…

【GESP】2023年12月图形化二级 -- 小杨报数

小杨报数 【题目描述】 小杨需要从 1 1 1到 N N N报数。在报数过程中&#xff0c;小杨希望跳过 M M M的倍数。例如&#xff0c;如果 N 5 N5 N5&#xff0c; M 2 M2 M2&#xff0c;那么小杨就需要依次报出 1 1 1&#xff0c; 3 3 3&#xff0c; 5 5 5。 默认小猫角色和白色背…

zblog中用户中心-邀请码注册插件的导出功能补充

自己加了一个导出未使用的邀请码功能&#xff0c;可惜我不是入驻作者&#xff0c;没有权限发布&#xff0c;之前被一条大河拒了&#xff0c;他说我抄他代码&#xff0c;不给我过审还冷嘲热讽&#xff0c;我一气之下&#xff0c;就没继续申请了&#xff0c;话说我是专业搞java开…