无名管道
无名管道适用于父子进程或兄弟进程之间的通信
pipe
//pipe(int *fd);
//参数:数组,fd[0]读,fd[1]写
//返回值:成功0,失败-1
//利用无名管道通信往往是父进程创建管道,子进程继承无名管道文件描述符
//read读数据默认阻塞
//write写数据,缓冲区满阻塞
//关闭所有读端,向管道写数据,写进程会收到SIGPIPE信号而退出
//fcntl(fd, F_SETFL, 0/O_NONBLOCK);
//功能:设置阻塞非阻塞
//参数:文件描述符,宏,0/O_NONBLOCK
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
pid_t pid;
int fd_pipe[2] = {0};
if(pipe(fd_pipe) < 0)
{
perror("pipe");
}
pid = fork();
if(pid == -1)
{
perror("fork");
return 0;
}
else if(pid == 0)
{
char *str = "pipe send helloworld\n";
write(fd_pipe[1], str, strlen(str));
_exit(0);
}
else if(pid > 0)
{
//fcntl(fd_pipe[0], F_SETFL, O_NONBLCOK);//设置读端非阻塞
//fcntl(fd_pipe[0], F_SETFL, 0); //设置读端阻塞
char str[100] = "";
wait(NULL);//挂起父进程,等待子进程结束或收到信号
read(fd_pipe[0], str, sizeof(str) - 1);
printf("无名管道接收消息:%s", str);
}
return 0;
}
执行结果:
dup,dup2
重定向文件描述符
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
//int dup(int oldfd)
//功能:复制一份打开的文件描述符oldfd,返回可用的最小 新的文件描述符
int main(int argc, char *argv[])
{
int fd, new_fd;
fd = open("./test.txt", O_RDWR);
if(fd < 0)
{
perror("open");
return 0;
}
close(1);
new_fd = dup(fd);
printf("new_fd = %d\n", new_fd);
printf("hello wrold\n");
//fflush(stdout);
write(new_fd, "mine\n", 5);
return 0;
}
//int dup2(int oldfd, int newfd)
// #include <stdio.h>
// #include <unistd.h>
// #include <stdlib.h>
// #include <sys/types.h>
// #include <sys/stat.h>
// #include <fcntl.h>
// int main(void)
// {
// int fd1;
// int fd2;
// fd1 = open("test.txt", O_CREAT | O_WRONLY, 0666);
// if (fd1 < 0)
// {
// perror("open:");
// exit(-1);
// }
// fd2 = dup2(fd1, 1);
// printf("fd2=%d\n", fd2);
// return 0;
// }
实例
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd_pipe[2];
pid_t pid = 0;
//创建管道
int ret = pipe(fd_pipe);
if(ret < 0)
perror("pipe");
pid = fork();
if(pid < 0)
{
perror("fork");
return 0;
}
else if(pid == 0)
{
dup2(fd_pipe[1], 1);
execlp("expr", "expr", "4", "+", "5", NULL);
_exit(0);
}
else if(pid > 0)
{
wait(NULL);
char str[100] = "";
read(fd_pipe[0], str, sizeof(str) - 1);
printf("num = %s\n", str);
}
return 0;
}
执行结果:
命名管道
适用于非血缘关系进程间通信
mkfifo
//命名管道:进程间通信
//int mkfifo(char *pathname, int num)
//参数:创建管道文件pathname,规定管道文件权限num
//返回值:成功0,失败非0
writefifo.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd;
int ret = mkfifo("fifo", 0666);
if(ret != 0)
perror("fifo");
//以只读打开管道
fd = open("./fifo", O_WRONLY);
if(fd <0)
{
perror("open");
}
printf("write fifo success\n");
write(fd, "hello fifo\n", 11);
return 0;
}
readfifo.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//命名管道:进程间通信
//int mkfifo(char *pathname, int num)
//参数:创建管道文件pathname,规定管道文件权限num
////返回值:成功0,失败非0
//以O_NONBLOCK打开特点
//1.先以只读方式打开,open不阻塞
//2.先以只写方式打开:只写open出错返回-1
//3.写进程退出会导致read阻塞不住
//4.读进程结束写进程收到信号结束进程
int main(int argc, char *argv[])
{
int fd;
char str[100] = "";
int ret = mkfifo("fifo", 0666);
if(ret != 0)
perror("fifo");
//以只读打开管道
fd = open("./fifo", O_RDONLY);
//以非阻塞方式打开
//fd = open("./fifo", O_RDONLY | O_NONBLOCK);
if(fd <0)
{
perror("open");
}
printf("write fifo success\n");
read(fd, str, sizeof(str));
printf("write fifo is %s\n", str);
return 0;
}
执行结果:
利用命名管道实现单机通信
readfifo.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//利用命名管道写一个进程通信工具
int main(int argc, char *argv[])
{
pid_t pid;
//1.创建管道
if(mkfifo("b_to_a", 0666) != 0)
perror("mkfifo");
int fd_write = open("a_to_b", O_WRONLY);
int fd_read = open("b_to_a", O_RDONLY);
if(fd_read < 0)
perror("open read");
if(fd_write < 0)
perror("open write");
pid = fork();
if(pid < 0)
{
perror("fork");
return 0;
}
else if(pid == 0)
{
while(1)
{
char str[100] = "";
fgets(str, sizeof(str) - 1, stdin);
str[strlen(str) - 1] = '\0';
write(fd_write, str, sizeof(str));
}
}
else if(pid > 0)
{
while(1)
{
char str[100] = "";
read(fd_read, str, sizeof(str));
printf("LIU:");
fflush(stdout);
printf("%s\n", str);
}
}
return 0;
}
writefifo.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//利用命名管道写一个进程通信工具
int main(int argc, char *argv[])
{
pid_t pid;
//1.创建管道
if(mkfifo("a_to_b", 0666) != 0)
perror("mkfifo");
int fd_read = open("a_to_b", O_RDONLY);
int fd_write = open("b_to_a", O_WRONLY);
if(fd_read < 0)
perror("open read");
if(fd_write < 0)
perror("open write");
pid = fork();
if(pid < 0)
{
perror("fork");
return 0;
}
else if(pid == 0)
{
while(1)
{
char str[100] = "";
fgets(str, sizeof(str) - 1, stdin);
str[strlen(str) - 1] = '\0';
write(fd_write, str, sizeof(str));
}
}
else if(pid > 0)
{
while(1)
{
char str[100] = "";
read(fd_read, str, sizeof(str));
printf("LI :");
fflush(stdout);
printf("%s\n", str);
}
}
return 0;
}
执行结果: