一、无名管道
1.1、特点:
1、没有名字,获取文件描述符的方法只有在创建时获得。
即无法通过open fopen 等函数获取文件描述符
2、第一个特点决定了无名管道通信只能存在于亲缘进程之间的通信。
即使用 fork 函数创建的进程之间
3、无名管道通信可被中断,即不能保证原子性(查百度吧,恶心的东西)
相关函数
函数原型 :int pipe(int pipefd[2])
return :0---->成功
-1--->失败
int pipefd[2] :pipefd[0]---->该文件描述符只有读取权限
pipefd[1]---->该文件描述符只有写入权限
1.2、相关事例代码
/******头文件自己写吧********/
#define BUFLEN 100
int main(void)
{
//信息存放
char buf[BUFLEN];
bzero(&buf, sizeof(buf));
//准备数组存放无名管道文件描述符
int fd[2];
int ret = pipe(fd);
if (ret == -1)
{
perror("pipe() filed");
exit(0);
}
pid_t pid = fork();
if (pid == -1)
{
perror("fork() filed");
exit(0);
}
//子进程发送信息
if (pid == 0)
{
printf("请输入给父进程的消息\n");
fgets(buf, 100, stdin);
write(fd[1], buf, strlen(buf));
exit(0);
}
//父进程接收信息
if (pid > 0)
{
read(fd[0], buf, strlen(buf));
printf("收到子进程消息: %s\n", buf);
wait(NULL);
exit(0);
}
}
程序最后没有关闭文件操作:因为完全没有必要
二、有名管道
2.1、特点
1、有名字,即可以通过 open 打开有名管道,即可以获得文件描述符。
2、有名字决定了有名管道可以在任意进程之间进行通信,因为可以在任意
进程获得有名管道的文件描述符。
相关函数
函数原型: int mkfifo(const char *pathname, mode_t mode)
return : 0---->成功
-1--->失败
pathname : 创建有名管道的名字(包括路径名)
mode : 参考 open 函数的参数 mode
注意:pathname 不能在共享文件下,因为管道是在 Linux 系统中特有的,
无法在 windows 系统下创建
常用相关错误码 :errno
EACCESS 参数pathname所指定的目录路径无可执行的权限
EEXIST 参数pathname所指定的文件已存在。
ENAMETOOLONG 参数pathname的路径名称太长。
ENOENT 参数pathname包含的目录不存在
ENOSPC 文件系统的剩余空间不足
ENOTDIR 参数pathname路径中的目录存在但却非真正的目录。
EROFS 参数pathname指定的文件存在于只读文件系统内。
2.2、相关事例代码
2.2.1、发送端
/********自己写头文件********/
#define BUFLEN 100
#define FIFO "/home/gec/fifo"
int main(void)
{
char buf[BUFLNE];
bzero(&buf, sizeof (buf));
//创建无名管道
int ret = mkfifo(FIFO, 0644);
//判断出错原因
if(ret == -1)
{
if (error != EEXIST)
{
perror("mkfifo() filed");
exit(0);
}
}
//数据写入有名管道
int fd = open(FIFO, O_RDWR);
fgets(buf, 100, stdin);
write(fd, buf, strlen(buf));
return 0;
}
2.2.2、接收端
/********就是不写头文件********/
#define BUFLEN 100
#define FIFO "/home/gec/fifo"
int main(void)
{
char buf[BUFLNE];
bzero(&buf, sizeof (buf));
//创建无名管道
int ret = mkfifo(FIFO, 0644);
//判断出错原因
if(ret == -1)
{
if (error != EEXIST)
{
perror("mkfifo() filed");
exit(0);
}
}
//将数据读出有名管道
int fd = open(FIFO, O_RDWR);
read(fd, buf, strlen(buf));
printf("收到发送端消息:%s\n", buf);
return 0;
}
三、检测管道缓冲区大小
3.1、直接上代码吧
//程序功能:检测有名管道缓冲区大小。(无名管道类推即可)
/************头文件***************/
int main(void)
{
//打开管道,不做判断了,如果出错请使用管道创建函数
int fd = open("/home/etc/fifo", O_RDWR);
//设置管道为非阻塞,这样写入失败会返回 -1
long state = fcntl(fd, F_GETFL);
state |= NONBLOCK;
fcntl(fd, F_GETFL, state);
char buf = 'a';
int i = 0;
while(-1 != (write(fd, &buf, sizeof (buf) ) ) )
i++;
printf("有名管道缓冲区大小:%d字节\n", i);
return 0;
}