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

news/2024/10/7 16:57:48 标签: linux, vim, 进程间通信, 管道, 信号

我要成为嵌入式高手之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.niftyadmin.cn/n/5398785.html

相关文章

c# string.Empty与“ “

背景&#xff1a; 在项目中加了几行代码&#xff0c;结果程序就莫名奇妙崩掉了。初步判断是有个 仔细分析了一下&#xff0c;添加的代码&#xff0c;用到 string.Empty来清空原来string变量中的值。然后就仔细研究了一下 string.Empty 和 “” 之间的区别 Empty是string类中的…

信号系统之滤波器比较

比较 1&#xff1a;模拟与数字滤波器 大多数数字信号源自模拟电子设备。**如果需要对信号进行滤波&#xff0c;是在数字化之前使用模拟滤波器&#xff0c;还是在数字化后使用数字滤波器更好&#xff1f;**将通过两个对比来回答问题。 目标是提供 1 kHz的低通滤波器。模拟端是…

存内计算技术大幅提升机器学习算法的性能—挑战与解决方案探讨

一.存内计算技术大幅机器学习算法的性能 1.1背景 人工智能技术的迅速发展使人工智能芯片成为备受关注的关键组成部分。在人工智能的构建中&#xff0c;算力是三个支柱之一&#xff0c;包括数据、算法和算力。目前&#xff0c;人工智能芯片的发展主要集中在两个方向&#xff1…

Linux笔记--基本操作指令

一、查看日期与日历 1.date指令 显示日期 #用法1:dateCST: China Standard Time时区&#xff0c;中国标准时间 #用法2: date 指定格式 [常用格式]: "%Y-%m-%d"(%F): 2022-07-25 "%H:%M:%S"(%T): 14:53:44 "%F %T" #用法3: date -d "-1 da…

蓝桥杯算法 一.

分析&#xff1a; 本题记录&#xff1a;m个数&#xff0c;异或运算和为0&#xff0c;则相加为偶数&#xff0c;后手获胜。 分析&#xff1a; 369*99<36500&#xff0c;369*100>36500。 注意&#xff1a;前缀和和后缀和问题

FPGA-学会使用vivado中的存储器资源RAM(IP核)

问题 信号源(例如ADC)以1us一个的速率产生12位的数据现要求获得连续1ms内的数据,通过串口以115200的波特率发到电脑。 分析 数据量是1000个 数据速率不匹配 数据内容未知 数据总数据量有限 数据的使用速度低于数据的产生速度 数据生产和消耗的位宽 数据量相对较…

Dataframe学习笔记:记录一下工作上使用的几种示例

Dataframe学习笔记&#xff1a;记录一下工作上使用的几种示例 0. 引言1. Dataframe 简介2. Dataframe 使用场景3. 创建测试数据4. 示例学习5. 总结 0. 引言 最近工作上开发 AI 应用&#xff0c;经常使用到 Dataframe&#xff0c;所以整理和记录一下工作上使用的几种示例。 1.…

【Docker】狂神说

图片后补 官网&#xff1a; https://www.docker.com/ Docker概述 Docker为什么出现 原因&#xff1a;环境配置不能跨平台 方案 传统方式&#xff1a;jar&#xff08;开发人员&#xff09; 部署&#xff08;运维人员&#xff09; 解决方式&#xff1a;开发打包上线一套流程 …