(二)linux系统编程之进程间通信

进程间通信相关概念

1.什么是IPC ?
即:进程间通信 InterProcess Communication
2.进程间通信常用的4种方式:
a.管道·简单
b.信号.系统统开销小
c.共享映射区·(有无血缘关亲的进程间通信都可以)
d.本地套接字-稳定

匿名管道

本质:内核缓冲区,是伪文件,不占磁盘空间
特点:数据写端流入,读端流出;对应2个文件描述符;操作管道的进程被销毁后管道自动释放,管道默认是阻塞的。
原理:内部实现方式:队列,先进先出。默认4k,大小会根据实际情况适当调整,但不会无限扩大。
局限性:队列一次只能读取一次,不能重复读取。是半双工的。(如对讲机)。适用于有血缘关系的进程。

创建匿名管道 int pipe(int pipefd[2]);

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<string.h>
int main(int argc,char* argv[])
{
    int fd[2];
    int ret=pipe(fd);
    if(ret==-1)
    {
        perror("pipe error");
        exit(1);
    }
    printf("pipe[0]=%d\tpipe[1]=%d\n",fd[0],fd[1]);
    close(fd[0]);
    close(fd[1]);
    return 0;
}
root@huislee-virtual-machine:/home/huislee/workspace/workspace/process/communication# ./a
pipe[0]=3       pipe[1]=4
注:0,1,2默认对应标准输出输入和错误。最小的为3,没有被占用就会直接分配,否则依次递增。

注:有血缘关系的进程之间通信fork的位置:
需要父子进程都可以操作管道的读和写,所以创建子进程需要在创建管道之后
在这里插入图片描述在这里插入图片描述父子间进程通信实现ps aux | grep bash

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<string.h>
int main(int argc,char* argv[])
{
    int fd[2];
    int ret=pipe(fd);
    if(ret==-1)
    {
        perror("pipe error");
        exit(1);
    }
    pid_t pid=fork();
    if(pid==-1)
    {
        perror("perror error");
        exit(1);
    }
    //父进程 ps aux
    if(pid>0)
    {
        //写管道操作 需要关闭读端
        close(fd[0]);
        //文件描述符重定向  标准输出->管道写端
        dup2(fd[1],STDOUT_FILENO);
        //执行ps aux
        execlp("ps","ps","aux",NULL);
        perror("execlp");
        exit(1);
    }
    //子进程 grep  "bash"
    else if(pid==0)
    {
        close(fd[1]);
        dup2(fd[0],STDIN_FILENO);
        execlp("grep","grep","--color=auto","bash",NULL);
    }
    printf("pipe[0]=%d\tpipe[1]=%d\n",fd[0],fd[1]);
    close(fd[0]);
    close(fd[1]);
    return 0;

}
huislee@huislee-virtual-machine:~/workspace/workspace/process/communication$ ./a
huislee    9020  0.0  0.0  24876  1632 pts/0    Ss+  09:33   0:00 bashroot       9455  0.0  0.0  24796  1604 pts/1    Ss+  09:36   0:00 -bash
huislee   10882  0.0  0.2  24876  4248 pts/2    Ss   10:20   0:00 /bin/bash
huislee   14622  0.0  0.0  16180  1020 pts/2    S+   15:56   0:00 grep --color=auto bash

兄弟进程通信实现ps aux | grep bash,父进程进行回收资源

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
    int fd[2], i = 0;
    int ret = pipe(fd);
    if (ret == -1)
    {
        perror("pipe error");
        exit(1);
    }
    for (i = 0; i < 2; i++)
    {
        pid_t pid;
        pid = fork();
        if (pid == 0)
        {
            break;
        }
        if (pid == -1)
        {
           perror("perror error");
            exit(1);
        }
    }
    //子进程1 ps aux
    if (i == 0)
    {
        //写管道操作 需要关闭读端
        close(fd[0]);
        //文件描述符重定向  标准输出->管道写端
        dup2(fd[1], STDOUT_FILENO);
        //执行ps aux
        execlp("ps", "ps", "aux", NULL);
        perror("execlp");
        exit(1);
    }
    //子进程2 grep  "bash"
    else if (i == 1)
    {
        close(fd[1]);
        dup2(fd[0], STDIN_FILENO);
        execlp("grep", "grep", "--color=auto", "bash", NULL);
    }
    else if (i == 2)
    {
        close(fd[0]);
        close(fd[1]);
        //回收子进程
        pid_t wpid;
        while ((wpid = waitpid(-1, NULL, WNOHANG)) != -1)
        {
            if (wpid == 0)
            {
                continue;
            }
            printf("child died pid=%d\n", wpid);
        }
    }
    printf("pipe[0]=%d\tpipe[1]=%d\n", fd[0], fd[1]);
    close(fd[0]);
    close(fd[1]);
    return 0;

}
root@huislee-virtual-machine:/home/huislee/workspace/workspace/process/communication# ./a
huislee    9020  0.0  0.0  24876  1636 pts/0    Ss+  09:33   0:00 bash
root       9455  0.0  0.1  24796  2640 pts/1    Ss   09:36   0:00 -bash
huislee   10882  0.0  0.2  24876  4248 pts/2    Ss+  10:20   0:00 /bin/bash
root      14831  0.0  0.0  16180  1132 pts/1    S+   16:32   0:00 grep --color=auto bash
child died pid=14830
child died pid=14831
pipe[0]=3       pipe[1]=4

查看管道缓冲区大小
命令:ulimit -a 函数:fpathconf

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

int main(int argc, char *argv[])
{
    int fd[2], i = 0;
    int ret = pipe(fd);
    if (ret == -1)
    {
        perror("pipe error");
        exit(1);
    }
    //测试管道默认大小
    long size = fpathconf(fd[0], _PC_PIPE_BUF);
    printf("size=%ld\n", size);
    printf("pipe[0]=%d\tpipe[1]=%d\n", fd[0], fd[1]);
    close(fd[0]);
    close(fd[1]);

    return 0;
}

huislee@huislee-virtual-machine:~/workspace/workspace/process/communication$ ./a
size=4096
pipe[0]=3       pipe[1]=6
huislee@huislee-virtual-machine:~/workspace$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7705
max locked memory       (kbytes, -l) 16384
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8    //512*8为管道大小
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7705
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值