Linux_3:进程间通信

发布于:2025-07-12 ⋅ 阅读:(16) ⋅ 点赞:(0)

IPC

1.什么是IPC?Inter Process Communication

2.进程间通信常用的几种方式

        1,管道通信:有名管道,无名管道

        2,信号- 系统开销小

        3,消息队列-内核的链表

        4,信号量-计数器

        5,共享内存

        6,内存映射

        7,套接字

无名管道

管道的概念

1.本质

内核缓冲区

伪文件-不占用磁盘空间

2特点:

两部分: 读端,写端,对应两个文件描述符

数据写端流入,读端流出

操作管理的进程被销毁之后,管道自动被释放

管道默认是阻塞的

管道的原理

1.内部实现方式:

队列-环形队列

特点:先进先出

2.缓冲区大小

默认4K,大小会根据实际情况做适当调整

管道的局限性

1.队列: 数据只能读取一次,不能重复读取

2.半双工:

单工:遥控器

半双工:对讲机

创建匿名管道

int pipe(int fd[2])

fd‐传出参数:

        fd[0]‐读端

        fd[1]‐写端

返回值:

        0:成功

        ‐1:创建失败

父子进程使用管道通信

实现 ps aux | grep "bash"

数据重定向:dup2

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
        int ret;
        int fd[2];

        ret = pipe(fd);
        if(ret == -1)
        {
                printf("pipe creat failed\n");
                exit(1);
        }
        printf("pipe creat success!\n");

        printf("fd[0] is %d\n",fd[0]);
        printf("fd[1] is %d\n",fd[1]);

        close(fd[0]);
        close(fd[1]);

        return 0;
}
~         

注012是标准输入输出和报错

       int dup2(int oldfd, int newfd);//新段指向旧端

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
        pid_t pid;
        int ret;
        int fd[2];

        ret = pipe(fd);
        if(ret == -1)
        {
                printf("pipe creat failed\n");
                exit(1);
        }

        printf("pipe creat success!\n");

        pid = fork();
        if(pid == -1)
        {
                printf("fork failed\n");
                exit(1);
        }

        if(pid > 0)
        {
                close(fd[0]);
                dup2(fd[1],STDOUT_FILENO);
                execlp("ps","ps","aux",NULL);
                perror("excelp");
                exit(1);
        }
        else if (pid == 0)
        {
                close(fd[1]);
                dup2(fd[0],STDIN_FILENO);
                execlp("grep","grep","bash","--color=auto",NULL);
        }

        return 0;
}

单个进程也可以使用管道
父子进程在使用管道的时候,父进程写的时候要关闭读,子进程读的时候要关闭写 

管道的读写行为

1.读操作

        1)有数据:read(fd[0]) 正常读,返回读出的字节数

        2)无数据:

                写端被全部关闭,read返回0,相当于读文件到了尾部

                没有全部关闭,read阻塞

2.写操作

        1)读端全部关闭:

                管道破裂,进程被终止

                内核给当前进程发送信号SIGPIPE-13,默认处理动作

        2)读端没全部关闭:

                缓冲区写满了,write阻塞

                缓冲区没满,write继续写,直到写满,阻塞

3.如何设置非阻塞?

1)默认读写两端都阻塞

2)设置读端为非阻塞pipe(fd):

        fcntl-变参函数:复制文件描述符-dup;修改文件属性-open的时候对应flag属性

        设置方法

//获取原来的flags 

int flags = fcntl(fd[0],F+GETFL); 

//设置新的flags 

flag |=O_NONBLOCK; 

fcntl(fd[0],F_SETFL,flags); 

fcntl(fd[0],F_SETFL,flags); 

查看管道缓冲区大小

命令:

ulimit -a

fpathconf

  long fpathconf(int fd, int name);

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
        int ret;
        int fd[2];

        ret = pipe(fd);
        if(ret == -1)
        {
                printf("pipe creat failed\n");
                exit(1);
        }
        printf("pipe creat success!\n");

        long size = fpathconf(fd[0],_PC_PIPE_BUF);
        printf("size id %ld\n",size);

        printf("fd[0] is %d\n",fd[0]);
        printf("fd[1] is %d\n",fd[1]);

        close(fd[0]);
        close(fd[1]);

        return 0;
}

有名管道

函数形式:int mkfifo(const char \*filename,mode_t mode);

功能:创建管道文件

参数:管道文件文件名,权限,创建的文件权限仍然和umask有关系。

返回值:创建成功返回0,创建失败返回-1。

特点

        有名管道

        在磁盘上有这样一个文件 ls -l ->p

        也是一个伪文件,在磁盘大小永久为0

        数据存在内核中有一个对应的缓冲区

        半双工通信方式

使用场景

没有血缘关系的进程间通信

创建方式

命令:mkfifo 管道名

函数:mkfifo()

 int mkfifo(const char *pathname, mode_t mode);

fifo文件可以使用io函数进程操作

open/close,read/write

不能执行lseek操作

读函数

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
        int ret;
        int fd;
        int nread;
        char readBuff[50] = {0};

        ret = mkfifo("/home/u/process/myfifo",0777);

        if(ret == -1)
        {
                return -1;
        }

        printf("creat file success!\n");

        fd = open("./myfifo",O_RDONLY);
        if(fd < 0)
        {
                return -1;
        }
        printf("open file success!\n");

        nread = read(fd,readBuff,50);
        printf("read %d byte from fifo :%s\n",nread,readBuff);

        close(fd);
        return 0;
}

写程序

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main()
{

        int fd;
        char *str = "hello world!";

        fd = open("./myfifo",O_WRONLY);
        if(fd < 0)
        {
                return -1;
        }
        printf("open file success!\n");

        write(fd,str,strlen(str));

        close(fd);

        return 0;
}
~      


网站公告

今日签到

点亮在社区的每一天
去签到