嵌入式学习Day26---Linux软件编程---进程间的通信

目录

一、管道

1.1.无名管道

1.应用场景和原理

 2.函数接口

3.注意点

 4.实例

1.2.有名管道

 1.应用场景和原理

2.函数接口

3.注意点

4.实例

​二、总结


一、管道

1.1.无名管道

1.应用场景和原理

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

        无名管道创建后,进程会获得操作管道的两个文件描述符,创建子进程时,子进程会拷贝得到父进程的操作无名管道的两个文件描述符,两个进程任务操作同一管道实现通信。     

 2.函数接口

        int pipefd[2];

        pipefd[0]------文件读描述符

        pipefd[1]------文件写描述符

 int pipe(int pipefd[2]);
        功能:
            创建一个用来通信的管道
        参数:
            pipefd:存放管道两端(读写)的文件描述符数组
        成功返回0 
        失败返回-1 

3.注意点

        1.如果管道中至少有一个写端:
            如果管道中有数据,直接读出
            如果管道中没有数据,会阻塞等待直到有数据写入后读出
        
        2.如果管道中没有写端:
            如果管道中有数据,直接读出 
            如果管道中没有数据,不会阻塞直接继续向下执行

        3.如果管道中至少有一个读端:
            如果管道没有写满,直接写入
            如果管道中写满(64k),则阻塞等待,等有数据读出才能继续写入

        4.如果管道中没有读端:
            向管道中写入数据会产生管道破裂信号

 4.实例

        在一个进程中创建一个子进程,然后子进程将字符串写入管道中,父进程在管道中读取子进程写入的信息并打印。

#include "../head.h"

int main(void)
{
    pid_t pid;
    char buff[4096] = {0};
    
    int pipfd[2];
    pipe(pipfd);

    pid = fork();
    if (pid == -1)
    {
        perror("");
        return -1;
    }

    if (pid == 0)
    {
        strcpy(buff, "hello world");
        write(pipfd[1], buff, strlen(buff));

    }else if (pid > 0)
    {
        read(pipfd[0], buff, sizeof(buff));
        printf(" buff= %s\n", buff);
        
    }

    return 0;

}

1.2.有名管道

 1.应用场景和原理

          无关系的两个进程

          通过管道在文件系统中的路径找到管道名,两个进程以读写的方式打开同一管道完成通信
 

2.函数接口

 mkfifo:
        int mkfifo(const char *pathname, mode_t mode);
        功能:
            创建一个管道 
        参数:
            pathname:管道文件的路径 
            mode:权限
        返回值:
            成功返回0 
            失败返回-1 

3.注意点

        有名管道必须读写两端同时加入后,才能继续向下执行;

        如果写入的进程没有执行写入,则读入的进程会等待,直到写入进程成功写入后,才执行读入从而执行完程序;

4.实例

        创建两个进程,也就是两个程序代码,一个程序负责往管道写数据,另一个程序负责从管道接受数据并打印出来。 

write.c

#include "../head.h"

extern int errno;


int main(void)
{
    int pid;
    int fd;

    pid = mkfifo("/tmp/myfifo.txt", 0664);
    if(pid == - 1 && errno != EEXIST)
    {
        perror("mkfifo");
        return -1;
    }

    fd = open("/tmp/myfifo.txt", O_WRONLY);
    if(fd == -1)
    {
        return -1;
    }

    printf("管道打开成功!\n");

    write(fd, "hello world", 11);

    close(fd);


    return 0;
}

read.c

#include "../head.h"

extern int errno;


int main(void)
{
    int pid;
    int fd;
    int ret = 0;
    char tmpbuff[4096] = {0};

    pid = mkfifo("/tmp/myfifo.txt", 0664);
    if(pid == - 1 && errno != EEXIST)
    {
        perror("mkfifo");
        return -1;
    }

    fd = open("/tmp/myfifo.txt", O_RDONLY);
    if(fd == -1)
    {
        return -1;
    }

    printf("读取成功!\n");

    ret = read(fd, tmpbuff, sizeof(tmpbuff));

    close(fd);

    printf("读取到%d个字节,%s\n", ret, tmpbuff);




    return 0;
}

先执行read.c,由于管道没有写入东西,因此在等待write.c写入东西。

然后执行write.c之后数据写入管道,read.c读入数据,成功打印。

二、总结

        2024年8月9日,第26天。今天主要学习了进程间的通信之管道,要区分清楚无名管道和管道的应用场景。无名管道用于进程和子进程,共享内核,通过建立无名管道,也就在内核的缓存区,建立读与写的管道,进程与子进程通过文件IO写入读出管道来进行通信。有名管道,需要通过建立管道文件,来将无关联的进程联系起来,使用文件io操作管道文件进程通信。前途光明,未来可期!

        加油!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值