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

相关文章

linux本机进程间通信之UDS详解

《linux本机进程间通信之UDS详解》文章介绍了Unix域套接字(UDS)的使用方法,这是一种在同一台主机上不同进程间通信的方式,UDS支持三种套接字类型:SOCK_STREAM、SOCK_DGRA... 目录基础概念本机进程间通信socket实现AF_INET数据收发示意图AF_Unix数据收发流程图A

MySQL 日期时间格式化函数 DATE_FORMAT() 的使用示例详解

《MySQL日期时间格式化函数DATE_FORMAT()的使用示例详解》`DATE_FORMAT()`是MySQL中用于格式化日期时间的函数,本文详细介绍了其语法、格式化字符串的含义以及常见日期... 目录一、DATE_FORMAT()语法二、格式化字符串详解三、常见日期时间格式组合四、业务场景五、总结一、

golang panic 函数用法示例详解

《golangpanic函数用法示例详解》在Go语言中,panic用于触发不可恢复的错误,终止函数执行并逐层向上触发defer,最终若未被recover捕获,程序会崩溃,recover用于在def... 目录1. panic 的作用2. 基本用法3. recover 的使用规则4. 错误处理建议5. 常见错

Python中多线程和多进程的基本用法详解

《Python中多线程和多进程的基本用法详解》这篇文章介绍了Python中多线程和多进程的相关知识,包括并发编程的优势,多线程和多进程的概念、适用场景、示例代码,线程池和进程池的使用,以及如何选择合适... 目录引言一、并发编程的主要优势二、python的多线程(Threading)1. 什么是多线程?2.

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

轻松上手MYSQL之JSON函数实现高效数据查询与操作

《轻松上手MYSQL之JSON函数实现高效数据查询与操作》:本文主要介绍轻松上手MYSQL之JSON函数实现高效数据查询与操作的相关资料,MySQL提供了多个JSON函数,用于处理和查询JSON数... 目录一、jsON_EXTRACT 提取指定数据二、JSON_UNQUOTE 取消双引号三、JSON_KE

MySQL数据库函数之JSON_EXTRACT示例代码

《MySQL数据库函数之JSON_EXTRACT示例代码》:本文主要介绍MySQL数据库函数之JSON_EXTRACT的相关资料,JSON_EXTRACT()函数用于从JSON文档中提取值,支持对... 目录前言基本语法路径表达式示例示例 1: 提取简单值示例 2: 提取嵌套值示例 3: 提取数组中的值注意

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解