进程间通信,无名管道pipe,有名管道mkfifo,信号的基础概念,signal函数

本文主要是介绍进程间通信,无名管道pipe,有名管道mkfifo,信号的基础概念,signal函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我要成为嵌入式高手之2月28日Linux高编第十一天!!

学习笔记 

进程间通信

总共6种通信方法,主要是前五种方式

第一种方式:管道

一、无名管道

只能用于具有亲缘关系的进程间通信

pipe

#include <unistd.h>

int pipe(int pipefd[2]);

功能:创建一个无名管道

参数:

        pipefd[0]:读

        pipefd[1]:写

返回值:成功返回0;失败返回-1

#include "head.h"int main(void)
{pid_t pid;int fd[2];int ret;char tmpbuff[4096];ret = pipe(fd);if (ret == -1){perror("fail to pipe");return -1;}pid = fork();if (pid == -1){perror("fail to fork");return -1;}if (pid == 0){strcpy(tmpbuff, "hello world!");write(fd[1], tmpbuff, strlen(tmpbuff));}else if (pid > 0){read(fd[0], tmpbuff, sizeof(tmpbuff));//read有等待作用,若文件标识符内没有可读内容,会等待到有可读内容printf("tmpbuff = %s\n", tmpbuff);}close(fd[0]);close(fd[1]);return 0;
}

 

无名管道的特性:

1、管道中至少有一个写端:

        读取数据时如果有数据直接读取;管道中没有数据,阻塞等待直到有数据写入,然后读出,继续向后执行 。

2、管道中没有写端:

        读取数据时,如果管道中有数据直接读取,管道中没有数据不阻塞等待直接向下执行

3、管道中至少有一个读端:

        写入数据时,如果管道中没有存满则直接写入,如果管道中存满则阻塞等待,直到有数据读出才继续写入

4、管道中没有读端:

        写入数据时,会产生管道破裂的错误,导致程序崩溃

二、有名管道

操作方式:

        打开管道文件(open)--->读写(read,write)管道文件--->关闭(close)管道文件

特性:有名管道必须读写两端同时加入才能继续向下执行

1、mkfifo

#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);

功能:创建一个管道文件

参数:

        pathname:管道文件的路径(名字包含在路径里)

        mdoe:权限(0777、0664)

返回值:成功返回0,失败返回-1;

练习:编写两个进程A B, A给B发送一条消息,B收到消息打印后给A回复一条消息

注:在接收函数之前都加入memset

#include "head.h"int main(void)
{int fatob = 0;int fbtoa = 0;char tmpbuff[1024] = {0};mkfifo("/tmp/ATOB", 0777);mkfifo("/tmp/BTOA", 0777);fatob = open("/tmp/ATOB", O_WRONLY);if (fatob == -1){perror("fail to open1");return -1;}fbtoa = open("/tmp/BTOA", O_RDONLY);if (fbtoa == -1){perror("fail to open2");return -1;}while (1){memset(tmpbuff, 0, sizeof(tmpbuff));gets(tmpbuff);write(fatob, tmpbuff, strlen(tmpbuff));memset(tmpbuff, 0, sizeof(tmpbuff));read(fbtoa, tmpbuff, sizeof(tmpbuff));printf("RECV:  %s\n", tmpbuff);}close(fatob);close(fbtoa);return 0;
}
#include "head.h"int main(void)
{int fatob = 0;int fbtoa = 0;char tmpbuff[1024] = {0};mkfifo("/tmp/ATOB", 0777);mkfifo("/tmp/BTOA", 0777);fatob = open("/tmp/ATOB", O_RDONLY);if (fatob == -1){perror("fail to open1");return -1;}fbtoa = open("/tmp/BTOA", O_WRONLY);if (fbtoa == -1){perror("fail to open2");return -1;}while (1){memset(tmpbuff, 0, sizeof(tmpbuff));read(fatob, tmpbuff, sizeof(tmpbuff));printf("RECV:  %s\n", tmpbuff);memset(tmpbuff, 0, sizeof(tmpbuff));gets(tmpbuff);write(fbtoa, tmpbuff, strlen(tmpbuff));}close(fatob);close(fbtoa);return 0;
}

 进阶难版

#include "head.h"pthread_t tid1;
pthread_t tid2;void *Write(void *arg)
{int fatob = 0;char tmpbuff[1024] = {0};while (1){mkfifo("/tmp/ATOB", 0777);fatob = open("/tmp/ATOB", O_WRONLY);if (fatob == -1){perror("fail to open1");return NULL;}memset(tmpbuff, 0, sizeof(tmpbuff));gets(tmpbuff);write(fatob, tmpbuff, strlen(tmpbuff));if (!strcmp(tmpbuff, ".quit")){break;}close(fatob);}pthread_cancel(tid2);return NULL;
}void *Read(void *arg)
{int fbtoa;char tmpbuff[1024] = {0};while (1){mkfifo("/tmp/BTOA", 0777);fbtoa = open("/tmp/BTOA", O_RDONLY);if (fbtoa == -1){perror("fail to open2");return NULL;}memset(tmpbuff, 0, sizeof(tmpbuff));read(fbtoa, tmpbuff, sizeof(tmpbuff));if (!strcmp(tmpbuff, ".quit")){break;}printf("RECV:  %s\n", tmpbuff);close(fbtoa);}pthread_cancel(tid1);return NULL;
}int main(void)
{int ret1 = 0;int ret2 = 0;ret1 = pthread_create(&tid1, NULL, Write, NULL);if (ret1 != 0){perror("fail to tid1");return -1;}ret2 = pthread_create(&tid2, NULL, Read, NULL);if (ret2 != 0){perror("fail to tid2");return -1;}pthread_join(tid1, NULL);pthread_join(tid2, NULL);return 0;
}
#include "head.h"pthread_t tid1;
pthread_t tid2;void *Write(void *arg)
{int fbtoa = 0;char tmpbuff[1024] = {0};while (1){mkfifo("/tmp/BTOA", 0777);fbtoa = open("/tmp/BTOA", O_WRONLY);if (fbtoa == -1){perror("fail to open1");return NULL;}memset(tmpbuff, 0, sizeof(tmpbuff));gets(tmpbuff);write(fbtoa, tmpbuff, strlen(tmpbuff));if (!strcmp(tmpbuff, ".quit")){break;}close(fbtoa);}pthread_cancel(tid2);return NULL;
}void *Read(void *arg)
{int fatob;char tmpbuff[1024] = {0};while (1){mkfifo("/tmp/ATOB", 0777);fatob = open("/tmp/ATOB", O_RDONLY);if (fatob == -1){perror("fail to open2");return NULL;}memset(tmpbuff, 0, sizeof(tmpbuff));read(fatob, tmpbuff, sizeof(tmpbuff));if (!strcmp(tmpbuff, ".quit")){break;}printf("RECV:  %s\n", tmpbuff);close(fatob);}pthread_cancel(tid1);return NULL;
}int main(void)
{int ret1 = 0;int ret2 = 0;ret1 = pthread_create(&tid1, NULL, Write, NULL);if (ret1 != 0){perror("fail to tid1");return -1;}ret2 = pthread_create(&tid2, NULL, Read, NULL);if (ret2 != 0){perror("fail to tid2");return -1;}pthread_join(tid1, NULL);pthread_join(tid2, NULL);return 0;
}

第二种方式:信号

信号用来实现内核层和用户层信息的交互,也可以用来实现进程间通信

一、信号的种类

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(异步IO)    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    

所有的信号都可以让进程结束

二、信号处理方式

1、缺省:

        按照系统默认的方式处理

2、忽略:

        不响应信号

3、捕捉:

        按照自己设定的方式处理信号

注意:

        9号信号(杀死)和19号信号(暂停)不可被忽略和捕捉,即只能按照缺省的方式处理

可键入:

        SIGINT:ctrl + c

        SIGQUIT:ctrl + \

        SIGTSTP:ctrl + z

4、signal

#include <signal.h>

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

功能:改变信号的处理方式

参数:

        signum:信号的编号

        handler:信号的处理方式

                SIG_IGN        忽略处理

                SIG_DFL        缺省处理

                函数首地址     捕捉处理

返回值:

        成功返回之前处理函数的首地址

        失败返回SIG_ERR

练习:

#include "head.h"void handler1(int signo)
{printf(" SIGINT信号来了!\n");return;
}void handler2(int signo)
{printf(" SIGQUIT信号来了!\n");return;
}void handler3(int signo)
{printf(" SIGTSTP信号来了!\n");return;
}int main(void)
{signal(SIGINT, handler1);signal(SIGQUIT, handler2);signal(SIGTSTP, handler3);while (1){}return 0;
}

这篇关于进程间通信,无名管道pipe,有名管道mkfifo,信号的基础概念,signal函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/761010

相关文章

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

[Linux]:进程(下)

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:Linux学习 贝蒂的主页:Betty’s blog 1. 进程终止 1.1 进程退出的场景 进程退出只有以下三种情况: 代码运行完毕,结果正确。代码运行完毕,结果不正确。代码异常终止(进程崩溃)。 1.2 进程退出码 在编程中,我们通常认为main函数是代码的入口,但实际上它只是用户级

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

C++操作符重载实例(独立函数)

C++操作符重载实例,我们把坐标值CVector的加法进行重载,计算c3=c1+c2时,也就是计算x3=x1+x2,y3=y1+y2,今天我们以独立函数的方式重载操作符+(加号),以下是C++代码: c1802.cpp源代码: D:\YcjWork\CppTour>vim c1802.cpp #include <iostream>using namespace std;/*** 以独立函数

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用@CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略,该策略要求请求的域名、协议和端口必须与提供资源的服务相同。如果不相同,则需要服务器显式地允许这种跨域请求。一般在springbo

函数式编程思想

我们经常会用到各种各样的编程思想,例如面向过程、面向对象。不过笔者在该博客简单介绍一下函数式编程思想. 如果对函数式编程思想进行概括,就是f(x) = na(x) , y=uf(x)…至于其他的编程思想,可能是y=a(x)+b(x)+c(x)…,也有可能是y=f(x)=f(x)/a + f(x)/b+f(x)/c… 面向过程的指令式编程 面向过程,简单理解就是y=a(x)+b(x)+c(x)

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显

C 语言基础之数组

文章目录 什么是数组数组变量的声明多维数组 什么是数组 数组,顾名思义,就是一组数。 假如班上有 30 个同学,让你编程统计每个人的分数,求最高分、最低分、平均分等。如果不知道数组,你只能这样写代码: int ZhangSan_score = 95;int LiSi_score = 90;......int LiuDong_score = 100;int Zhou