匿名管道由于没有名字,只能用于具有亲缘关系的进程间通信。
为了克服这个缺点,就提出了有名管道(FIFO
),也称为命名管道
、FIFO文件
。
有名管道
FIFO在文件系统中作为一个特殊的文件而存在并且在文件系统中可见,所以有名管道可以实现不相关进程间通信,但FIFO中的内容却存放在内存中。
1. 创建有名管道
- 方式1:可以使用命令创建有名管道:
$ mkfifo 名字
- 方式2:使用函数
mkfifo()
函数创建有名管道 - 参数说明:
- pathname:管道名称的路径;
- mode:FIFO的权限,和open是一样的;如0666;
- 返回值:成功返回0,失败返回-1,并设置对应的errno;
使用mkfifo()
创建了FIFO后,就可以使用open()
打开它,常见的文件I/O函数都可以用于FIFO。
2.特点:
a.存在于内存中
b.在系统中有一个对应名称。
c.文件大小为0bytes
d.可以用于任何进程间通信。
e.管道文件都不支持定位操作,如:lseek、fseek。
f.有名管道操作也符合前面管道的操作特点。
a.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
if (argc != 2)
{
printf("Usage: %s <filename>\n",argv[0]);
return -1;
}
if (mkfifo(argv[1],0666) < 0 && errno != EEXIST)
{
perror("mkfifo fail");
return -1;
}
printf("----mkfifo -- success\n");
int fd = open(argv[1],O_WRONLY);
//int fd = open(argv[1],O_RDWR);
if (fd < 0)
{
perror("open fail");
return -1;
}
printf("----open success---\n");
//从键盘输入数据 写到 管道中
char buf[1024];
while (1)
{
fgets(buf,sizeof(buf),stdin);
write(fd,buf,strlen(buf)+1);
if (strncmp(buf,"quit",4) == 0)
{
remove(argv[1]);
close(fd);
break;
}
}
return 0;
}
b.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
if (argc != 2)
{
printf("Usage: %s <filename>\n",argv[0]);
return -1;
}
if (mkfifo(argv[1],0666) < 0 && errno != EEXIST)
{
perror("mkfifo fail");
return -1;
}
printf("----mkfifo -- success\n");
int fd = open(argv[1],O_RDONLY);
// int fd = open(argv[1],O_RDWR);
if (fd < 0)
{
perror("open fail");
return -1;
}
printf("----open success---\n");
//从管道中读数据
char buf[1024];
while (1)
{
read(fd,buf,sizeof(buf));
printf("buf = %s",buf);
if (strncmp(buf,"quit",4) == 0)
{
remove(argv[1]);
close(fd);
break;
}
}
return 0;
}
信号
1、概念:
(1)信号是进程间通信的方式之一,这种方式不能传输数据,只是在内核中传递一个信号(整数),信号表示一个整数。
(2)不同信号的值所代表的信号不同。
(3)允许用户自定义信号,自定义信号的含义由程序员自行定义,但是信号值不允许和系统默认拥有的信号值一样。
(4)软中断:异步通信方式,步调不一致。在软件层面类似于一个中断过程。
(5) 信号处理函数的注册函数 typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
参数:int signum(信号编号)
sighandler_t handler(做怎样的处理或函数指针指向的信号处理函数)
2.常见信号:
3.收到信号的三种处理方式
(1)用户自定义: 通过将一个信号与用户自定义的处理函数关联起来,进程可以捕获并处理信号。当进程收到与已注册的处理函数关联的信号时,操作系统会调用相应的处理函数,允许程序员指定自定义的行为。
(2)默认行为: 对于大多数信号,操作系统定义了默认的行为。这些默认行为通常是终止进程,生成核心转储文件,或暂停进程执行等。当进程收到信号时,如果没有设置信号的自定义处理函数,将会执行操作系统默认的行为。
(3)忽略信号: 进程可以选择忽略某些信号,这意味着进程在收到该信号时不做任何动作。这通常用于对某些不需要处理的信号进行过滤,或者是在特定情况下暂时屏蔽某些信号的影响。
例: