linux 进程 管道通信(无名, 命名)

1. 概述:
该demo主要实现linux下进程之间的管道通信(无名, 命名), 相关接口介绍可以参考<<UNIX环境高级编程>>
在这里插入图片描述

2. 场景(半双工):
父进程简单地通过管道(无名, 命名)将数据发送给子进程

3. 测试:
在这里插入图片描述

/*
demo_process_IPC_pipe.c
进程编程demo(无名管道)

IPC相关的命令: ipcs ipcrm(释放IPC)
查看进程属性: ulimit -a

1. FILE * popen ( const char * command , const char * type )
    type 为 "r" 返回command的标准输出; type 为 "w" 返回command的标准输入
    函数执行时, 会调用pipe, fork, exec, dup, wait等相关函数

2. int pclose ( FILE * stream )

3. int dup2(int oldfd, int newfd)
    目标描述符将变成源描述符的复制品(STDOUT_FILENO STDIN_FILENO)
    换句话说, 两个文件描述符现在都指向同一个文件, 并且是函数第一个参数指向的文件

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

#define MAX_BUF     64

int main(int argc, char **argv){

    pid_t pid;
    int fd[2];

    /*
    w ->fd[1] → fd[0] → r
    即, fd[0]为读打开, f[1]为写打开
    */
    if(pipe(fd) < 0){
        /*printf("pipe:%s\n", strerror(errno));*/
        perror("pipe:");
        return -1;
    }

    /*
    父 -> 子
    */
    pid = fork();
    if(pid < 0){
        perror("fork:");
        close(fd[0]);
        close(fd[1]);
        return -1;
    }else if(pid == 0){
        usleep(100 * 1000);

        printf("child process\n");    /*子进程*/

        char buf[MAX_BUF];

        close(fd[1]);    /*关闭写*/

        /*
        读一个写端已被关闭的管道时, 在所有数据都被读取后, 返回0, 表示文件结束
        */
        memset(buf, 0, sizeof(buf));
        if(read(fd[0], buf,sizeof(buf)) < 0){
            perror("read:");
        }

        printf("child process\t read\t buf = %s\n", buf);

        close(fd[0]);    /*关闭读*/
    }else{
        printf("parant process\n");    /*父进程*/

        char buf[MAX_BUF] = "demo_process_IPC_pipe";

        close(fd[0]);    /*关闭读*/

        /*
        写一个读端已被关闭的管道时, 产生SIGPIPE信号
        写入管道的数据长度小于PIPE_BUF字节时是原子操作
        超过PIPE_BUF字节的写入可能是非原子的, 内核可能会将数据与其他进程写入的数据交错
        */
        if(write(fd[1], buf, strlen(buf)) < 0){
            perror("write:");
        }

        printf("parant process\t write\t buf = %s\n", buf);

        wait(NULL);

        close(fd[1]);    /*关闭写*/
    }

    return 0;
}
/*
demo_process_IPC_mkfifo.c
进程编程demo(命名管道)

IPC相关的命令: ipcs ipcrm(释放IPC)
查看进程属性: ulimit -a

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

#define MAX_BUF     64

#define FIFONAME    "/dev/fifo"

int main(int argc, char **argv){

    pid_t pid;

    if (access(FIFONAME, F_OK) < 0){
        if(mkfifo(FIFONAME, 600) < 0){
            /*printf("mkfifo:%s\n", strerror(errno));*/
            perror("mkfifo:");
            return -1;
        }
    }

    /*
    父 -> 子
    */
    pid = fork();
    if(pid < 0){
        perror("fork:");
        unlink(FIFONAME);
        return -1;
    }else if(pid == 0){
        usleep(100 * 1000);

        printf("child process\n");    /*子进程*/

        int fd = -1;
        char buf[MAX_BUF];

        /*
        O_RDWR     : 可读可写方式打开
        O_RDONLY   : 只读方式打开
        O_WRONLY   : 只写方式打开
        O_NONBLOCK : 非阻塞I/O
            置位 : 只读open立即返回
                   只写open时, 如果没有进程为读打开FIFO, 则返回–1. 并置errno值为ENXIO
            不置位 : 只读open要阻塞到有进程为写打开FIFO
                     只写open要阻塞到有进程为读打开FIFO
        */
        fd = open(FIFONAME, O_RDONLY);
        if(fd < 0){
            perror("open:");
            return -1;
        }

        memset(buf, 0x0, sizeof(buf));
        if(read(fd, buf, sizeof(buf)) < 0){
            perror("read:");
        }

        printf("child process\t read\t buf = %s\n", buf);

        close(fd);
    }else{
        printf("parant process\n");    /*父进程*/

        int fd = -1;
        char buf[MAX_BUF] = "demo_process_IPC_mkfifo";

        fd = open(FIFONAME, O_WRONLY);
        if(fd < 0){
            perror("open:");
            return -1;
        }

        /*
        写入管道的数据长度小于PIPE_BUF字节时是原子操作
        超过PIPE_BUF字节的写入可能是非原子的, 内核可能会将数据与其他进程写入的数据交错
        */
        if(write(fd, buf, strlen(buf)) < 0){
            perror("write:");
        }

        printf("parant process\t write\t buf = %s\n", buf);

        wait(NULL);

        close(fd);

        //remove(FIFONAME);
        unlink(FIFONAME);
    }

    return 0;
}
#Makefile
CC := gcc
INCLUDE = -I /home/demo/include/

all:
	$(CC) demo_process_IPC_pipe.c $(INCLUDE) -o demo_process_IPC_pipe -Wall -Werror
	$(CC) demo_process_IPC_mkfifo.c $(INCLUDE) -o demo_process_IPC_mkfifo -Wall -Werror

clean:
	rm demo_process_IPC_pipe demo_process_IPC_mkfifo
发布了12 篇原创文章 · 获赞 16 · 访问量 1736

猜你喜欢

转载自blog.csdn.net/lpaim/article/details/104807831