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

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/414634.html

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

相关文章

ETH开源PPO算法学习

前言 项目地址&#xff1a;https://github.com/leggedrobotics/rsl_rl 项目简介&#xff1a;快速简单的强化学习算法实现&#xff0c;设计为完全在 GPU 上运行。这段代码是 NVIDIA Isaac GYM 提供的 rl-pytorch 的进化版。 下载源码&#xff0c;查看目录&#xff0c;整个项目…

2024年3月5-7日第12届生物发酵技术装备展-奥博仪表

参观企业介绍 潍坊奥博仪表科技发展有限公司成立于2002年3月&#xff0c;注册资金1000万元&#xff0c;已有20多年的发展历程&#xff0c;是一家专业从事流量仪表开发、生产与测控系统集成的高新技术企业和双软认证企业。 目前公司以仪表、通讯产品、自控系统、软件的研发、生…

DVWA 靶场之 Command Injection(命令执行)middlehigh

对于 middle 难度的 我们直接先看源码 <?phpif( isset( $_POST[ Submit ] ) ) {// Get input$target $_REQUEST[ ip ];// Set blacklist$substitutions array(&& > ,; > ,);// Remove any of the characters in the array (blacklist).$target str_rep…

Pytest教程:一种利用 Python Pytest Hook 机制的软件自动化测试网络数据抓包方法

随着计算机技术的发展&#xff0c;使得网络应用的数量不断增加&#xff0c;因此网络数据抓包成为了网络应用开发和测试中非常重要的一部分。目前&#xff0c;已有许多网络数据抓包工具可供使用&#xff0c;例如 Wireshark、Tcpdump、Fiddler 等&#xff0c;但这些工具需要手动配…

5G网络频谱划分与应用

频率越大&#xff0c;波长越短。补充&#xff1a;微波频段&#xff1a;300MHZ~3000GHZ。 5G网络工作频带与带宽配置 &#xff08;1&#xff09; FR1:410MHZ~7125MHZ。 FR2&#xff1a;24250MHZ~52600MHZ 注&#xff1a;早期将6GHZ已下频段作为FR1&#xff0c;但是最新的频段…

Python打发无聊时光:10.用flask创造按键控制的网页小游戏

游戏介绍: 《秦蓝大冒险》是一款简单而紧张的追逐游戏。在这个游戏中&#xff0c;玩家将控制一名名叫“吕千”的角色&#xff0c;试图在一个封闭的空间内逃避一个名为“秦蓝”的追逐者。随着时间的推移&#xff0c;“秦蓝”会不断追踪玩家的位置&#xff0c;努力捕捉到他。 游…

C语言中如何进行内存管理

主页&#xff1a;17_Kevin-CSDN博客 收录专栏&#xff1a;《C语言》 C语言是一种强大而灵活的编程语言&#xff0c;但与其他高级语言不同&#xff0c;它要求程序员自己负责内存的管理。正确的内存管理对于程序的性能和稳定性至关重要。 一、引言 C 语言是一门广泛使用的编程语…

2.1_6 线程的实现方式和多线程模型

文章目录 2.1_6 线程的实现方式和多线程模型&#xff08;一&#xff09;线程的实现方式&#xff08;1&#xff09;用户级线程&#xff08;2&#xff09;内核级线程 &#xff08;二&#xff09;多线程模型&#xff08;1&#xff09;一对一模型&#xff08;2&#xff09;多对一模…

stable diffusion webUI之赛博菩萨【秋葉】——工具包新手安裝与使用教程

stable diffusion webUI之赛博菩萨【秋葉】——工具包新手安裝与使用教程 AI浪潮袭来&#xff0c;还是学习学习为妙赛博菩萨【秋葉】简介——&#xff08;葉ye&#xff0c;四声&#xff0c;同叶&#xff09;A绘世启动器.exe&#xff08;sd-webui-aki-v4.6.x&#xff09;工具包安…

VirtualBox虚拟机配置双网卡

安装完后Linux后。下一步需要设置Linux的网络。为了便于学习测试&#xff0c;通常我们需要虚拟机能通宿主机和外网。类似达到下面的效果。虚拟机跟宿主本机和外网&#xff0c;及另外一台同网段的虚拟机也是相通 解决思路是-->配置双网卡&#xff0c;网卡1使用NAT网络模式&a…

vue组件中data为什么必须是一个函数

查看本专栏目录 关于作者 还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#x…

fiddler抓包工具使用(一)

一、fiddler简介 1. 简介 fiddler是一款强大的抓包工具&#xff0c;它的原理以web代理服务器的形式进行工作fiddler是好用的web调试工具之一 能记录所有客户端和服务器的http和https请求修改输入、输出数据包数据允许监视设置断点弱网测试 2. 工作原理 代理就是在客户端和服…

QT C++实战:实现用户登录页面及多个界面跳转

主要思路 一个登录界面&#xff0c;以管理员Or普通用户登录管理员&#xff1a;一个管理员的操作界面&#xff0c;可以把数据录入到数据库中。有返回登陆按钮&#xff0c;可以选择重新登陆&#xff08;管理员Or普通用户普通用户&#xff1a;一个主界面&#xff0c;负责展示视频…

java动态代理面试题,java反射原理面试题

01 并发宝典&#xff1a;面试专题 面试专题分为四个部分&#xff0c;分别如下 Synchronized 相关问题 可重入锁 ReentrantLock 及其他显式锁相关问题 Java 线程池相关问题 Java 内存模型相关问题 1.1 Synchronized 相关问题&#xff08;这里整理了八问&#xff09; 问题一…

揭示预处理中的秘密!(二)

目录 ​编辑 1. #运算符 2. ##运算符 3. 命名约定 4. #undef 5. 命令行定义 6. 条件编译 7. 头文件的被包含的方式 8.嵌套文件包含 9. 其他预处理指令 10. 完结散花 悟已往之不谏&#xff0c;知来者犹可追 …

【Go-Zero】测试API查询信息无法返回数据库信息与api、rpc文件编写规范

【Go-Zero】测试API查询信息无法返回数据库信息与api、rpc文件编写规范 大家好 我是寸铁&#x1f44a; 总结了一篇测试API查询信息无法返回数据库信息与api、rpc文件编写规范的文章✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 问题背景 大家好&#xff0c;我是寸铁&#xff01…

C++——基础语法(2):函数重载、引用

4. 函数重载 函数重载就是同一个函数名可以重复被定义&#xff0c;即允许定义相同函数名的函数。但是相同名字的函数怎么在使用的时候进行区分呢&#xff1f;所以同一个函数名的函数之间肯定是要存在不同点的&#xff0c;除了函数名外&#xff0c;还有返回类型和参数两部分可以…

前后端项目-part03

文章目录 5.4.4 机构名称5.4.4.1 创建实体类Company5.4.4.2 创建实体类CompanyMapper5.4.4.3 创建实体类CompanyService5.4.4.4 创建实体类CompanyController5.4.4.5 后端测试5.4.4.6 修改basic.js5.4.4.7 修改course.vue5.4.4.8 测试5.4.5 课程标签5.4.5.1 效果5.4.5.2 修改co…

golang学习5,glang的web的restful接口

1. //返回json r.GET("/getJson", controller.GetUserInfo) package mainimport (/*"net/http"*/"gin/src/main/controller""github.com/gin-gonic/gin" )func main() {r : gin.Default()r.GET("/get", func(ctx *…

【Linux系统化学习】信号概念和信号的产生

目录 信号的概念 从生活中的例子中感知信号 前台进程和后台进程 前台进程 后台进程 操作系统如何知道用户向键盘写入数据了&#xff1f; 进程如何得知自己收到了信号&#xff1f; 信号捕捉 signal函数 Core Dump&#xff08;核心转储&#xff09; 信号产生的方式 通…