Linux 8
·
有名管道(Named Pipe / FIFO)
有名管道是一种有文件名的管道,允许无亲缘关系的进程进行通信。
| 特性 | 无名管道(Pipe) | 有名管道(FIFO) |
|---|---|---|
| 文件名 | 无 | 有(文件系统中的特殊文件) |
| 通信范围 | 只能父子/兄弟进程 | 任意进程 |
| 创建方式 | pipe() |
mkfifo() |
| 打开方式 | 自动打开 | 需要用 open() |
| 持久性 | 随进程结束消失 | 文件存在,可重复使用 |
| 可见性 | 不可见 | 在文件系统中可见 |
| 打开模式 | 行为 |
|---|---|
O_RDONLY |
阻塞直到有进程以 O_WRONLY 打开 |
O_WRONLY |
阻塞直到有进程以 O_RDONLY 打开 |
O_RDWR |
不阻塞(但一般不推荐,会破坏管道意义) |
O_NONBLOCK |
非阻塞模式,立即返回 |
创建
#include "head.h"
int main(int argc,const char *argv[])
{
int ret = mkfifo("pipe",0664);
if(ret<0 && errno !=EEXIST)//错误码不是"文件已存在"
//允许管道文件已经存在,不视为错误。
{
perror("mkfifo error");
return -1;
}
int fd = open("pipe",O_WRONLY);
if(fd<0)
{
perror("open error");
return -1;
}
ssize_t size=write(fd,"hello world",11);
printf("size=%ld\n",size);
close(fd);
return 0;
}
#include "head.h"
int main(int argc,const char *argv[])
{
int ret = mkfifo("pipe",0664);
if(ret<0 && errno !=EEXIST)
{
perror("mkfifo error");
return -1;
}
int fd = open("pipe",O_RDONLY);
if(fd<0)
{
perror("open error");
return -1;
}
char buff[1024]={0};
ssize_t size=read(fd,buff,sizeof(buff));
printf("size=%ld,buff=%s\n",size,buff);
close(fd);
remove("pipe");
return 0;
}
| 单工 | 只能一个方向 | 广播电台 | 电视、收音机 |
| 半双工 | 双向交替 | 对讲机 | 管道、I2C |
| 全双工 | 双向同时 | 电话 | 网线、SPI |
半双工式对话
#include <stdio.h>
#include "head.h"
int main(int argc, const char *argv[])
{
int ret1 = mkfifo("pipe1", 0664);
int ret2 = mkfifo("pipe2", 0664);
if (ret1 < 0 && ret2 < 0 && errno != EEXIST)
{
perror("mkfifo error");
return -1;
}
char buff[1024] = {0};
int fd1 = open("pipe1", O_WRONLY);
int fd2 = open("pipe2", O_RDONLY);
while (1)
{
fgets(buff, sizeof(buff), stdin);
write(fd1, buff, strlen(buff));
memset(buff, 0, sizeof(buff));//将缓冲区 buff 的所有字节设置为 0
//接收数据前清空缓冲区,防止残留数据干扰。
//read 是二进制字节流读取函数,不知道也不关心数据是否是字符串,所以不会自动添加 \0
ssize_t size = read(fd2, buff, sizeof(buff));
printf("size = %ld,buff = %s\n", size, buff);
}
close(fd1);
close(fd2);
return 0;
}
#include"head.h"
int main(int argc,const char *argv[])
{
int ret1 = mkfifo("pipe1",0664);
int ret2 = mkfifo("pipe2",0664);
if(ret1<0&&ret2<0&&errno!=EEXIST)
{
perror("mkfifo error");
return -1;
}
char buff[1024]={0};
int fd1=open("pipe1",O_RDONLY);
int fd2=open("pipe2",O_WRONLY);
while(1)
{
ssize_t size=read(fd1,buff,sizeof(buff));
printf("size = %ld,buff = %s\n", size, buff);
fgets(buff,sizeof(buff),stdin);
write(fd2,buff,strlen(buff));
}
close(fd1);
close(fd2);
return 0;
}
全双工对话
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "head.h"
int main(int argc, const char *argv[])
{
int ret1 = mkfifo("pipe3", 0664);
int ret2 = mkfifo("pipe4", 0664);
if (ret1 < 0 && ret2 < 0 && errno != EEXIST)
{
perror("mkfifo error");
return -1;
}
char buff[1024] = {0};
pid_t pid = fork();
if (pid > 0)
{
int fp1 = open("pipe3", O_WRONLY);
if (fp1 < 0)
{
perror("error");
return -1;
}
while (1)
{
fgets(buff, sizeof(buff), stdin);
ssize_t size = write(fp1, buff, strlen(buff));
printf("write size = %ld\n", size);
if (0 == strcmp(buff, ".quit\n"))
{
break;
}
}
close(fp1);
wait(NULL);
}
else if (0 == pid)
{
int fp2 = open("pipe4", O_RDONLY);
if (fp2 < 0)
{
perror("error");
return -1;
}
while (1)
{
memset(buff, 0, sizeof(buff));
ssize_t size = read(fp2, buff, sizeof(buff));
printf("size = %ld,buff = ---%s---\n", size, buff);
if (0 == strcmp(buff, ".quit\n"))
{
break;
}
printf("d->c: %s\n", buff);
}
close(fp2);
}
else
{
perror("fork error");
}
return 0;
}
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "head.h"
int main(int argc, const char *argv[])
{
int ret1 = mkfifo("pipe3", 0664);
int ret2 = mkfifo("pipe4", 0664);
if (ret1 < 0 && ret2 < 0 && errno != EEXIST)
{
perror("mkfifo error");
return -1;
}
char buff[1024] = {0};
pid_t pid = fork();
if (pid > 0)
{
int fp2 = open("pipe4", O_WRONLY);
if (fp2 < 0)
{
perror("error");
return -1;
}
while (1)
{
fgets(buff, sizeof(buff), stdin);
ssize_t size = write(fp2, buff, strlen(buff));
printf("write size = %ld\n", size);
if (0 == strcmp(buff, ".quit\n"))
{
break;
}
}
close(fp2);
wait(NULL);
}
else if (0 == pid)
{
int fp1 = open("pipe3", O_RDONLY);
if (fp1 < 0)
{
perror("error");
return -1;
}
while (1)
{
memset(buff, 0, sizeof(buff));
ssize_t size = read(fp1, buff, sizeof(buff));
printf("size = %ld,buff = ---%s---\n", size, buff);
if (0 == strcmp(buff, ".quit\n"))
{
break;
}
printf("c->d: %s\n", buff);
}
close(fp1);
}
else
{
perror("fork error");
}
return 0;
}
信号
信号:进程间的通知机制(异步通信)
信号:软中断。CPU正在执行的任务可以被一个信号打断,中断后执行新的任务,新的任务结束继续执行之前的任务。
信号的操作:
-
发送信号 : kill、kill()
-
注册信号:signal()
-
信号的处理方式
忽略:不处理
缺省:按照操作系统默认方式处理
捕获:按照自定义方式处理





#include "head.h"
int cnt = 1;
void handler(int signum)
{
printf("chaoshi%d\n", cnt);
if (3 == cnt)
{
exit(0);
}
cnt++;
alarm(3);
}
int main(int argc, const char *argv[])
{
char buff[512] = {0};
signal(SIGALRM, handler);
while (1)
{
alarm(3);
fgets(buff, sizeof(buff), stdin);
cnt = 1;
}
}
更多推荐




所有评论(0)