进程间通信,无名管道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

相关文章

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

从基础到高级详解Python数值格式化输出的完全指南

《从基础到高级详解Python数值格式化输出的完全指南》在数据分析、金融计算和科学报告领域,数值格式化是提升可读性和专业性的关键技术,本文将深入解析Python中数值格式化输出的相关方法,感兴趣的小伙... 目录引言:数值格式化的核心价值一、基础格式化方法1.1 三种核心格式化方式对比1.2 基础格式化示例

redis-sentinel基础概念及部署流程

《redis-sentinel基础概念及部署流程》RedisSentinel是Redis的高可用解决方案,通过监控主从节点、自动故障转移、通知机制及配置提供,实现集群故障恢复与服务持续可用,核心组件包... 目录一. 引言二. 核心功能三. 核心组件四. 故障转移流程五. 服务部署六. sentinel部署

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

Python Counter 函数使用案例

《PythonCounter函数使用案例》Counter是collections模块中的一个类,专门用于对可迭代对象中的元素进行计数,接下来通过本文给大家介绍PythonCounter函数使用案例... 目录一、Counter函数概述二、基本使用案例(一)列表元素计数(二)字符串字符计数(三)元组计数三、C

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Python WebSockets 库从基础到实战使用举例

《PythonWebSockets库从基础到实战使用举例》WebSocket是一种全双工、持久化的网络通信协议,适用于需要低延迟的应用,如实时聊天、股票行情推送、在线协作、多人游戏等,本文给大家介... 目录1. 引言2. 为什么使用 WebSocket?3. 安装 WebSockets 库4. 使用 We

Linux系统管理与进程任务管理方式

《Linux系统管理与进程任务管理方式》本文系统讲解Linux管理核心技能,涵盖引导流程、服务控制(Systemd与GRUB2)、进程管理(前台/后台运行、工具使用)、计划任务(at/cron)及常用... 目录引言一、linux系统引导过程与服务控制1.1 系统引导的五个关键阶段1.2 GRUB2的进化优

Python中的filter() 函数的工作原理及应用技巧

《Python中的filter()函数的工作原理及应用技巧》Python的filter()函数用于筛选序列元素,返回迭代器,适合函数式编程,相比列表推导式,内存更优,尤其适用于大数据集,结合lamb... 目录前言一、基本概念基本语法二、使用方式1. 使用 lambda 函数2. 使用普通函数3. 使用 N

MySQL中REPLACE函数与语句举例详解

《MySQL中REPLACE函数与语句举例详解》在MySQL中REPLACE函数是一个用于处理字符串的强大工具,它的主要功能是替换字符串中的某些子字符串,:本文主要介绍MySQL中REPLACE函... 目录一、REPLACE()函数语法:参数说明:功能说明:示例:二、REPLACE INTO语句语法:参数