无名管道
#include <unistd.h>
int pipe(int pipefd[2]);
无名管道主要用在父子进程直接进行通讯,但是只能父发子收或者父收子发,发送和接收不能同时进行。
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd[2];
int pid;
char buf[128] = {0};
if(pipe(fd) < 0)
{
printf("creat error\n");
}
pid = fork();
if(pid > 0)
{
printf("father is writing\n");
close(fd[0]);
write(fd[1],"hello world",strlen("hello world"));
wait(NULL);
}
else if(pid == 0)
{
sleep(3);
printf("this is child read:\n");
close(fd[1]);
read(fd[0],buf,128);
printf("read from father: %s\n",buf);
exit(0);
}
else
{
printf("error\n");
}
return 0;
}
管道的函数是pipe()函数,除此之外还定义了一个fd[2]的数组。这个数组的用处在于是否要进行读写。fd[1]代表写,fd[0]代表读,之前说过,无名管道不能同时收发。所以,当我们进行写的操作时,要把读给关闭,也就是close(fd[0]),读操作就相反。
代码刚开始先调用pipe()函数创建一个管道,然后创建一个进程,用pid来接收进程id。如果pid大于0,说明进入了父进程。先把fd[0]关闭,然后用write()函数进行写入操作。然后调用wait()函数等待子进程结束。
当pid等于0时,进入了子进程,先延时3秒防止父进程没写完。然后关闭fd[1]写的操作,随后调用read()函数读取数据到buf数组里,最后调用exit()函数退出。
CLC@Embed_Learn:~/test_11.8$ gcc test1.c
CLC@Embed_Learn:~/test_11.8$ ./a.out
father is writing
this is child read:
read from father: hello world
能正确读到数据。
命名管道
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
命名管道可以再两个进程间相互通讯,但是和无名管道一样,不能同时进行收发。pathname是文件名,mode是文件的权限。
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd;
char *str = "hello world";
fd = open("./file2",O_WRONLY);
if(fd == -1)
{
printf("creat error\n");
}
write(fd,str,strlen(str));
close(fd);
return 0;
}
这是发送的方代码,先打开一个文件,然后把hello world写入,最后关闭文件。
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
int main()
{
int fd;
char buf[30] = {0};
if(mkfifo("./file2",0600) == -1)
{
printf("mkfifo failuer\n");
}
fd = open("./file2",O_RDONLY);
if(fd == -1)
{
printf("open error\n");
}
int n_read = read(fd,buf,30);
printf("read %d byte from fifo, context : %s\n",n_read,buf);
close(fd);
return 0;
}
这是接收方的代码,使用mkfifo()函数把发送方打开的文件设为管道并且赋予文件权限。然后打开设为管道的文件,读取数据,最后关闭文件。
CLC@Embed_Learn:~/test_11.8$ gcc write.c -o w
CLC@Embed_Learn:~/test_11.8$ gcc read.c -o r
CLC@Embed_Learn:~/test_11.8$ ./r
mkfifo failuer
read 11 byte from fifo, context : hello world
这是第一个终端运行的命令,进行发送的操作。
CLC@Embed_Learn:~/test_11.8$ ./w
这是第二个终端执行的命令,非常简单,只需要运行起来就好了。