一、父子进程共享内容

相同处

全局变量,.data, .text、堆栈,环境变量,用户id工作目录。

重点:文件描述符,mmap建立的映射区。

不同处

进程ID、fork返回值、各自父进程、进程运行时间、定时器,未决信号集。

子进程复制了父进程的用户空间,遵循读时共享,写时复制原则。

二、gdb调试

set follow-fork-mode child // 跟踪子进程

set follow-fork-mode parent // 跟踪父进程【默认】

三、进程间通信

  • 管道:使用最简单
  • 信号:开销最小
  • 共享内存:适用于无血缘关系
  • 本地套接字:最稳定

一、匿名管道pipe

特点:单向通信,每端都是只能读或者只能写。数据一点被读走,就不复存在。只能在一个方向上流动。只能在有血缘关系的进程间使用。

管道使用环形队列实现,f[0]为读端,f[1]为写端。

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

int main(){
    int fd[2];
    char buf[1025];
    int ret = pipe(fd), n;
    if (ret == -1) {
        perror("pipe error");
        return 0;
    }

    memset(buf, 0, 1025);
    pid_t pid = fork();

    if (pid == -1) {
        perror("fork error");
        return 0;
    } else if (pid == 0){
        close(fd[1]);
        n = read(fd[0], buf, 1024);
        if (-1 == n) {
            perror("read error");
            close(fd[0]);
            return 0;
        }
        printf("read %d byte data: %s\n", n, buf);
        close(fd[0]);
    } else {
        close(fd[0]);
        strcpy(buf, "HelloWorld");
        n = write(fd[1], buf, strlen(buf));
        if (n == -1) {
            perror("write error");
            close(fd[1]);
            return 0;
        }
        wait(0);
        close(fd[1]);
    }
    return 0;
}
  • 读端不读,写端一直写:导致缓冲区写满数据,会阻塞写入,知道数据被读出。
  • 写端不写,读端一直读:导致读端读不到数据,一直阻塞。
  • 读端关闭,写端一直写:导致写端收到信号SIGPIPE
  • 写端关闭,读端一直读:导致读端在读完缓冲区数据后返回0,即相当于读到EOF

二、命名管道fifo

fifo其实是一个本地文件,一端创建后另外一端可以通过open打开,和文件一样执行read,write等操作,同时支持非阻塞操作。

特点:适用于无血缘关系的进程通信。支持双向通信,数据会一直存在于文件中,可以重复读写。

read.c

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

int main() {
    int ret = mkfifo("my_fifo", 0755);
    int n;
    if (ret == -1) {
        perror("mkdfifo error");
        return 0;
    }

    char buf[1025];
    int fd = open("my_fifo", O_RDONLY);
    if (-1 == fd) {
        perror("open error");
        return 0;
    }
    bzero(buf, 1025);
    n = read(fd, buf, 1024);
    if (n == -1) {
        perror("");
    }
    printf("%s\n", buf);
    close(fd);

    unlink("my_fifo");

    return 0;
}

write.c

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

int main(){
    int fd = open("my_fifo", O_WRONLY);
    if (-1 == fd) {
        perror("open error");
        return 0;
    }

    int n = write(fd, "HelloWorld", 11);
    if (-1 == n){
        perror("write error");
        return 0;
    }

    close(fd);
    return 0;
}
最后修改:2018 年 12 月 16 日
如果觉得我的文章对你有用,请随意赞赏