一、父子进程共享内容
相同处
全局变量,.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;
}
此处评论已关闭