管道使用举例
2014-10-26 21:44
218 查看
//----------------------------------------------------
//AUTHOR: lanyang123456
//DATE: 2014-10-26
//----------------------------------------------------
管道是一种两个进程间进行单向通信的机制。因为管道传递数据的单向性,管道又称为半双工管道。管道的这一特点决定了其使用的局限性。具有以下特点:
*** 数据只能由一个进程流向另一个进程(其中一个读管道,一个写管道);如果要进行双工通信,需要建 立两个管道。
*** 管道只能用于父子进程或者兄弟进程间通信。,也就是说管道只能用于具有亲缘关系的进程间通信。
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int
main(int argc, char *argv[])
{
int pipefd[2];
pid_t cpid;
char buf;
if (argc != 2) {
fprintf(stderr, "Usage: %s <string>\n", argv[0]);
exit(EXIT_FAILURE);
}
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
printf("before fork\n");
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Child reads from pipe */
close(pipefd[1]); /* Close unused write end */
printf("child get parent's:\n");
while (read(pipefd[0], &buf, 1) > 0)
write(STDOUT_FILENO, &buf, 1);
write(STDOUT_FILENO, "\n", 1);
close(pipefd[0]);
printf("--------child exit-------\n");
_exit(EXIT_SUCCESS);
//exit(EXIT_SUCCESS);
} else { /* Parent writes argv[1] to pipe */
close(pipefd[0]); /* Close unused read end */
printf("parent give child %s\n", argv[1]);
write(pipefd[1], argv[1], strlen(argv[1]));
close(pipefd[1]); /* Reader will see EOF */
wait(NULL); /* Wait for child */
printf("---------parent exit-------\n");
exit(EXIT_SUCCESS);
}
}
$ gcc -o test pipe1.c
$ ./test hello
before fork
parent give child hello
child get parent's:
hello
--------child exit-------
---------parent exit-------
有个地方值得关注一下,就是exit和_exit的区别:
exit() 做的工作包括:执行退出处理函数;关闭所有标准iO流(这会导致所有的缓冲数据都会被冲洗,即写到文件);然后调用_exit();
如果这样执行程序,可看到区别。
$ ./test hello > tmp
$ cat tmp
hello
before fork
parent give child hello
---------parent exit-------
下面的代码通过管道实现重定向, 将标准输出定向到管道的写入端,标准输入定向到管道的读取端。
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define MAXLEN 2048
int main()
{
int pipefd[2];
int ret = pipe(pipefd);
if (ret < 0) {
perror("pipe");
exit(EXIT_FAILURE);
}
int pid = fork();
if (pid < 0) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) {//child
close(pipefd[0]); //关闭不需要的端
if (pipefd[1] != STDOUT_FILENO) { //重定向管道输出端到标准输出
if (dup2(pipefd[1], STDOUT_FILENO) != STDOUT_FILENO) {
perror("dup2");
exit(EXIT_FAILURE);
}
close(pipefd[1]);
}
//write(STDOUT_FILENO, "one ", strlen("one "));
execlp("ls", "ls", "-l", (char *)0); //由于将stdout重定向为管道的输入端,所以这行的执行结果被存放在管道输入端
_exit(127);
} else if(pid > 0) {//parent
close(pipefd[1]);
char buffer[MAXLEN];
char ret;
int nread = 0;
memset(buffer, 0, MAXLEN);
if (pipefd[0] != STDIN_FILENO) { //重定向管道读端到标准输入
if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) {
perror("dup2");
exit(EXIT_FAILURE);
}
close(pipefd[0]);
}
/*do {
ret = read(STDIN_FILENO, buffer + nread, MAXLEN - 1);
if (ret < 0 && errno == EINTR) {
continue;
} else if (ret > 0) {
nread += ret;
}
}
while ( ret > 0);
printf("%s", buffer);
fflush(stdout);*/
execlp("wc", "wc", "-l", (char *)0); //这里wc后面没有给出文件名,所以从标准输入读取,而标准输入端被定向为管道输出端
//,所以读取的数据即为上面ls -l的执行结果
} else {
printf("fork error/n");
}
return 0;
}
$./test2
17
17行
再举一例:
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define MAXLEN 2048
int main()
{
int pipefd[2];
int ret = pipe(pipefd);
if (ret < 0) {
perror("pipe");
exit(EXIT_FAILURE);
}
int pid = fork();
if (pid < 0) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) {//child
close(pipefd[0]); //关闭不需要的端
if (pipefd[1] != STDOUT_FILENO) { //重定向管道输出端到标准输出
if (dup2(pipefd[1], STDOUT_FILENO) != STDOUT_FILENO) {
perror("dup2");
exit(EXIT_FAILURE);
}
close(pipefd[1]);
}
printf("child write to pipe.\n");//现在向标准输出写入,即是向管道写入
printf("child write to pipe.\n");
fflush(stdout);//必须的,若无,上面的写到管道的字符串不会立即发送到管道
write(STDOUT_FILENO, "one ", strlen("one "));
execlp("ls", "ls", "-l", (char *)0); //由于将stdout重定向为管道的输入端,所以这行的执行结果被存放在管道输入端
_exit(127);
} else if(pid > 0) {//parent
close(pipefd[1]);
char buffer[MAXLEN];
int ret;
int nread = 0;
memset(buffer, 0, MAXLEN);
do {
ret = read(pipefd[0], buffer + nread, MAXLEN - 1);
if (ret < 0 && errno == EINTR) {
continue;
} else if (ret > 0) {
nread += ret;
}
}
while ( ret > 0);
printf("parent output: %s", buffer);
printf("\n");
//execlp("wc", "wc", "-l", (char *)0); //这里wc后面没有给出文件名,所以从标准输入读取,而标准输入端被定向为管道输出端
//,所以读取的数据即为上面ls -l的执行结果
} else {
printf("fork error/n");
}
return 0;
}
$ gcc -o test2.1 pipe2.1.c
$ ./test2.1
parent output: child write to pipe.
child write to pipe.
one total 88
-rwxrwxr-x 1 lanyang lanyang 7671 10月 26 21:01 fifo
-rw-rw-r-- 1 lanyang lanyang 1341 10月 26 21:02 fifo.c
-rw-rw-r-- 1 lanyang lanyang 1209 10月 26 21:01 fifo.c~
-rw-rw-r-- 1 lanyang lanyang 1498 10月 25 16:46 notes
-rw-rw-r-- 1 lanyang lanyang 1503 10月 25 10:06 notes~
-rw-rw-r-- 1 lanyang lanyang 1194 10月 26 16:33 pipe1.1.c
-rw-rw-r-- 1 lanyang lanyang 1194 10月 26 16:32 pipe1.1.c~
-rw-rw-r-- 1 lanyang lanyang 1410 10月 26 15:26 pipe1.c
-rw-rw-r-- 1 lanyang lanyang 1426 10月 26 15:22 pipe1.c~
-rw-rw-r-- 1 lanyang lanyang 1751 10月 26 16:49 pipe2.1.c
-rw-rw-r-- 1 lanyang lanyang 1758 10月 26 21:25 pipe2.c
-rw-rw-r-- 1 lanyang lanyang 1738 10月 26 17:23 pipe2.c~
-rwxrwxr-x 1 lanyang lanyang 7770 10月 25 15:30 test
-rwxrwxr-x 1 lanyang lanyang 7623 10月 26 16:33 test1.1
-rwxrwxr-x 1 lanyang lanyang 7674 10月 26 17:23 test2
-rwxrwxr-x 1 lanyang lanyang 7944 10月 26 21:29 test2.1
-rw-rw-r-- 1 lanyang lanyang 70 10月 26 21:21 tmp
若程序改为:
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define MAXLEN 2048
int main()
{
int pipefd[2];
int ret = pipe(pipefd);
if (ret < 0) {
perror("pipe");
exit(EXIT_FAILURE);
}
int pid = fork();
if (pid < 0) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) {//child
close(pipefd[0]); //关闭不需要的端
if (pipefd[1] != STDOUT_FILENO) { //重定向管道输出端到标准输出
if (dup2(pipefd[1], STDOUT_FILENO) != STDOUT_FILENO) {
perror("dup2");
exit(EXIT_FAILURE);
}
close(pipefd[1]);
}
printf("child write to pipe.\n");//现在向标准输出写入,即是向管道写入
printf("child write to pipe.\n");
//fflush(stdout);//必须的,若无,上面的写到管道的字符串不会立即发送到管道
//write(STDOUT_FILENO, "one ", strlen("one "));
execlp("ls", "ls", "-l", (char *)0); //由于将stdout重定向为管道的输入端,所以这行的执行结果被存放在管道输入端
_exit(127);
} else if(pid > 0) {//parent
close(pipefd[1]);
char buffer[MAXLEN];
int ret;
int nread = 0;
memset(buffer, 0, MAXLEN);
do {
ret = read(pipefd[0], buffer + nread, MAXLEN - 1);
if (ret < 0 && errno == EINTR) {
continue;
} else if (ret > 0) {
nread += ret;
}
}
while ( ret > 0);
printf("parent output: %s", buffer);
printf("\n");
//execlp("wc", "wc", "-l", (char *)0); //这里wc后面没有给出文件名,所以从标准输入读取,而标准输入端被定向为管道输出端
//,所以读取的数据即为上面ls -l的执行结果
} else {
printf("fork error/n");
}
return 0;
}
$ gcc -o test2.1 pipe2.1.c
lanyang@lanyang-ThinkPad-Edge-E431:~/exercise/pipe$ ./test2.1
parent output: total 92
-rwxrwxr-x 1 lanyang lanyang 7671 10月 26 21:01 fifo
-rw-rw-r-- 1 lanyang lanyangn 1341 10月 26 21:02 fifo.c
-rw-rw-r-- 1 lanyang lanyang 1209 10月 26 21:01 fifo.c~
-rw-rw-r-- 1 lanyang lanyang 1498 10月 25 16:46 notes
-rw-rw-r-- 1 lanyang lanyang 1503 10月 25 10:06 notes~
-rw-rw-r-- 1 lanyang lanyang 1194 10月 26 16:33 pipe1.1.c
-rw-rw-r-- 1 lanyang lanyang 1194 10月 26 16:32 pipe1.1.c~
-rw-rw-r-- 1 lanyang lanyang 1410 10月 26 15:26 pipe1.c
-rw-rw-r-- 1 lanyang lanyang 1426 10月 26 15:22 pipe1.c~
-rw-rw-r-- 1 lanyang lanyang 2838 10月 26 21:31 pipe2.1.c
-rw-rw-r-- 1 lanyang lanyang 2836 10月 26 21:31 pipe2.1.c~
-rw-rw-r-- 1 lanyang lanyang 1758 10月 26 21:25 pipe2.c
-rw-rw-r-- 1 lanyang lanyang 1738 10月 26 17:23 pipe2.c~
-rwxrwxr-x 1 lanyang lanyang 7770 10月 25 15:30 test
-rwxrwxr-x 1 lanyang lanyang 7623 10月 26 16:33 test1.1
-rwxrwxr-x 1 lanyang lanyang 7674 10月 26 17:23 test2
-rwxrwxr-x 1 lanyang lanyang 7835 10月 26 21:32 test2.1
-rw-rw-r-- 1 lanyang lanyang 70 10月 26 21:21 tmp
会发现使用printf写到管道中的数据丢失了。这是因为printf带有缓冲区,标准输入重定向为管道写断后,变为全缓冲。printf的数据不会立刻放到管道中。
后面再执行exec,输出的数据会将前面的数据覆盖,于是管道中就不会有printf的数据了。这个地方如果使用write则会正常,因为write不带缓冲,直接写到管道中。如果带缓冲区的printf,则fflush一下。
命名管道:
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define FNAME "/tmp/TestFIFO"
int main()
{
char buffer[32] = {0};
//注意下面的0666
//4 2 1分别表示读、写和执行权限
//第一个6表示文件所有者具有读写权限
//第二个6表示同组用户权限
//地三个6表示其他用户读写权限
int mkRet = mkfifo(FNAME, 0666); //mkfifo的第一个参数必须是不存在的文件,执行第二次就会出错
if (mkRet == -1)
{
perror("mkfifo failed\n");
exit(1);
}
int pid = fork();
if (pid < 0) {
perror("fork error");
exit(1);
}
else if (pid == 0) //子进程
{
int fd = open(FNAME, O_RDONLY);
read(fd, buffer, sizeof(buffer)); //read会一直等待可读数据
printf("r content = %s\n", buffer);
close(fd);
}
else if (pid > 0)
{
// wait(NULL);
char s[] = "what a nice day!";
int fd = open(FNAME, O_WRONLY);
size_t len = sizeof(s);
printf("len = %d\n", len);
write(fd, s, sizeof(s));
printf("write over!\n");
close(fd);
}
return 0;
}
$ gcc -o fifo fifo.c
$ ./fifo
len = 17
write over!
r content = what a nice day!
第二次执行,则会出错。
$ ./fifo
mkfifo failed
: File exists
参考
http://blog.csdn.net/wutaozhao/article/details/6010665
http://blog.csdn.net/ljianhui/article/details/10202699
//AUTHOR: lanyang123456
//DATE: 2014-10-26
//----------------------------------------------------
管道是一种两个进程间进行单向通信的机制。因为管道传递数据的单向性,管道又称为半双工管道。管道的这一特点决定了其使用的局限性。具有以下特点:
*** 数据只能由一个进程流向另一个进程(其中一个读管道,一个写管道);如果要进行双工通信,需要建 立两个管道。
*** 管道只能用于父子进程或者兄弟进程间通信。,也就是说管道只能用于具有亲缘关系的进程间通信。
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int
main(int argc, char *argv[])
{
int pipefd[2];
pid_t cpid;
char buf;
if (argc != 2) {
fprintf(stderr, "Usage: %s <string>\n", argv[0]);
exit(EXIT_FAILURE);
}
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
printf("before fork\n");
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Child reads from pipe */
close(pipefd[1]); /* Close unused write end */
printf("child get parent's:\n");
while (read(pipefd[0], &buf, 1) > 0)
write(STDOUT_FILENO, &buf, 1);
write(STDOUT_FILENO, "\n", 1);
close(pipefd[0]);
printf("--------child exit-------\n");
_exit(EXIT_SUCCESS);
//exit(EXIT_SUCCESS);
} else { /* Parent writes argv[1] to pipe */
close(pipefd[0]); /* Close unused read end */
printf("parent give child %s\n", argv[1]);
write(pipefd[1], argv[1], strlen(argv[1]));
close(pipefd[1]); /* Reader will see EOF */
wait(NULL); /* Wait for child */
printf("---------parent exit-------\n");
exit(EXIT_SUCCESS);
}
}
$ gcc -o test pipe1.c
$ ./test hello
before fork
parent give child hello
child get parent's:
hello
--------child exit-------
---------parent exit-------
有个地方值得关注一下,就是exit和_exit的区别:
exit() 做的工作包括:执行退出处理函数;关闭所有标准iO流(这会导致所有的缓冲数据都会被冲洗,即写到文件);然后调用_exit();
如果这样执行程序,可看到区别。
$ ./test hello > tmp
$ cat tmp
hello
before fork
parent give child hello
---------parent exit-------
下面的代码通过管道实现重定向, 将标准输出定向到管道的写入端,标准输入定向到管道的读取端。
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define MAXLEN 2048
int main()
{
int pipefd[2];
int ret = pipe(pipefd);
if (ret < 0) {
perror("pipe");
exit(EXIT_FAILURE);
}
int pid = fork();
if (pid < 0) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) {//child
close(pipefd[0]); //关闭不需要的端
if (pipefd[1] != STDOUT_FILENO) { //重定向管道输出端到标准输出
if (dup2(pipefd[1], STDOUT_FILENO) != STDOUT_FILENO) {
perror("dup2");
exit(EXIT_FAILURE);
}
close(pipefd[1]);
}
//write(STDOUT_FILENO, "one ", strlen("one "));
execlp("ls", "ls", "-l", (char *)0); //由于将stdout重定向为管道的输入端,所以这行的执行结果被存放在管道输入端
_exit(127);
} else if(pid > 0) {//parent
close(pipefd[1]);
char buffer[MAXLEN];
char ret;
int nread = 0;
memset(buffer, 0, MAXLEN);
if (pipefd[0] != STDIN_FILENO) { //重定向管道读端到标准输入
if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) {
perror("dup2");
exit(EXIT_FAILURE);
}
close(pipefd[0]);
}
/*do {
ret = read(STDIN_FILENO, buffer + nread, MAXLEN - 1);
if (ret < 0 && errno == EINTR) {
continue;
} else if (ret > 0) {
nread += ret;
}
}
while ( ret > 0);
printf("%s", buffer);
fflush(stdout);*/
execlp("wc", "wc", "-l", (char *)0); //这里wc后面没有给出文件名,所以从标准输入读取,而标准输入端被定向为管道输出端
//,所以读取的数据即为上面ls -l的执行结果
} else {
printf("fork error/n");
}
return 0;
}
$./test2
17
17行
再举一例:
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define MAXLEN 2048
int main()
{
int pipefd[2];
int ret = pipe(pipefd);
if (ret < 0) {
perror("pipe");
exit(EXIT_FAILURE);
}
int pid = fork();
if (pid < 0) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) {//child
close(pipefd[0]); //关闭不需要的端
if (pipefd[1] != STDOUT_FILENO) { //重定向管道输出端到标准输出
if (dup2(pipefd[1], STDOUT_FILENO) != STDOUT_FILENO) {
perror("dup2");
exit(EXIT_FAILURE);
}
close(pipefd[1]);
}
printf("child write to pipe.\n");//现在向标准输出写入,即是向管道写入
printf("child write to pipe.\n");
fflush(stdout);//必须的,若无,上面的写到管道的字符串不会立即发送到管道
write(STDOUT_FILENO, "one ", strlen("one "));
execlp("ls", "ls", "-l", (char *)0); //由于将stdout重定向为管道的输入端,所以这行的执行结果被存放在管道输入端
_exit(127);
} else if(pid > 0) {//parent
close(pipefd[1]);
char buffer[MAXLEN];
int ret;
int nread = 0;
memset(buffer, 0, MAXLEN);
do {
ret = read(pipefd[0], buffer + nread, MAXLEN - 1);
if (ret < 0 && errno == EINTR) {
continue;
} else if (ret > 0) {
nread += ret;
}
}
while ( ret > 0);
printf("parent output: %s", buffer);
printf("\n");
//execlp("wc", "wc", "-l", (char *)0); //这里wc后面没有给出文件名,所以从标准输入读取,而标准输入端被定向为管道输出端
//,所以读取的数据即为上面ls -l的执行结果
} else {
printf("fork error/n");
}
return 0;
}
$ gcc -o test2.1 pipe2.1.c
$ ./test2.1
parent output: child write to pipe.
child write to pipe.
one total 88
-rwxrwxr-x 1 lanyang lanyang 7671 10月 26 21:01 fifo
-rw-rw-r-- 1 lanyang lanyang 1341 10月 26 21:02 fifo.c
-rw-rw-r-- 1 lanyang lanyang 1209 10月 26 21:01 fifo.c~
-rw-rw-r-- 1 lanyang lanyang 1498 10月 25 16:46 notes
-rw-rw-r-- 1 lanyang lanyang 1503 10月 25 10:06 notes~
-rw-rw-r-- 1 lanyang lanyang 1194 10月 26 16:33 pipe1.1.c
-rw-rw-r-- 1 lanyang lanyang 1194 10月 26 16:32 pipe1.1.c~
-rw-rw-r-- 1 lanyang lanyang 1410 10月 26 15:26 pipe1.c
-rw-rw-r-- 1 lanyang lanyang 1426 10月 26 15:22 pipe1.c~
-rw-rw-r-- 1 lanyang lanyang 1751 10月 26 16:49 pipe2.1.c
-rw-rw-r-- 1 lanyang lanyang 1758 10月 26 21:25 pipe2.c
-rw-rw-r-- 1 lanyang lanyang 1738 10月 26 17:23 pipe2.c~
-rwxrwxr-x 1 lanyang lanyang 7770 10月 25 15:30 test
-rwxrwxr-x 1 lanyang lanyang 7623 10月 26 16:33 test1.1
-rwxrwxr-x 1 lanyang lanyang 7674 10月 26 17:23 test2
-rwxrwxr-x 1 lanyang lanyang 7944 10月 26 21:29 test2.1
-rw-rw-r-- 1 lanyang lanyang 70 10月 26 21:21 tmp
若程序改为:
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define MAXLEN 2048
int main()
{
int pipefd[2];
int ret = pipe(pipefd);
if (ret < 0) {
perror("pipe");
exit(EXIT_FAILURE);
}
int pid = fork();
if (pid < 0) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) {//child
close(pipefd[0]); //关闭不需要的端
if (pipefd[1] != STDOUT_FILENO) { //重定向管道输出端到标准输出
if (dup2(pipefd[1], STDOUT_FILENO) != STDOUT_FILENO) {
perror("dup2");
exit(EXIT_FAILURE);
}
close(pipefd[1]);
}
printf("child write to pipe.\n");//现在向标准输出写入,即是向管道写入
printf("child write to pipe.\n");
//fflush(stdout);//必须的,若无,上面的写到管道的字符串不会立即发送到管道
//write(STDOUT_FILENO, "one ", strlen("one "));
execlp("ls", "ls", "-l", (char *)0); //由于将stdout重定向为管道的输入端,所以这行的执行结果被存放在管道输入端
_exit(127);
} else if(pid > 0) {//parent
close(pipefd[1]);
char buffer[MAXLEN];
int ret;
int nread = 0;
memset(buffer, 0, MAXLEN);
do {
ret = read(pipefd[0], buffer + nread, MAXLEN - 1);
if (ret < 0 && errno == EINTR) {
continue;
} else if (ret > 0) {
nread += ret;
}
}
while ( ret > 0);
printf("parent output: %s", buffer);
printf("\n");
//execlp("wc", "wc", "-l", (char *)0); //这里wc后面没有给出文件名,所以从标准输入读取,而标准输入端被定向为管道输出端
//,所以读取的数据即为上面ls -l的执行结果
} else {
printf("fork error/n");
}
return 0;
}
$ gcc -o test2.1 pipe2.1.c
lanyang@lanyang-ThinkPad-Edge-E431:~/exercise/pipe$ ./test2.1
parent output: total 92
-rwxrwxr-x 1 lanyang lanyang 7671 10月 26 21:01 fifo
-rw-rw-r-- 1 lanyang lanyangn 1341 10月 26 21:02 fifo.c
-rw-rw-r-- 1 lanyang lanyang 1209 10月 26 21:01 fifo.c~
-rw-rw-r-- 1 lanyang lanyang 1498 10月 25 16:46 notes
-rw-rw-r-- 1 lanyang lanyang 1503 10月 25 10:06 notes~
-rw-rw-r-- 1 lanyang lanyang 1194 10月 26 16:33 pipe1.1.c
-rw-rw-r-- 1 lanyang lanyang 1194 10月 26 16:32 pipe1.1.c~
-rw-rw-r-- 1 lanyang lanyang 1410 10月 26 15:26 pipe1.c
-rw-rw-r-- 1 lanyang lanyang 1426 10月 26 15:22 pipe1.c~
-rw-rw-r-- 1 lanyang lanyang 2838 10月 26 21:31 pipe2.1.c
-rw-rw-r-- 1 lanyang lanyang 2836 10月 26 21:31 pipe2.1.c~
-rw-rw-r-- 1 lanyang lanyang 1758 10月 26 21:25 pipe2.c
-rw-rw-r-- 1 lanyang lanyang 1738 10月 26 17:23 pipe2.c~
-rwxrwxr-x 1 lanyang lanyang 7770 10月 25 15:30 test
-rwxrwxr-x 1 lanyang lanyang 7623 10月 26 16:33 test1.1
-rwxrwxr-x 1 lanyang lanyang 7674 10月 26 17:23 test2
-rwxrwxr-x 1 lanyang lanyang 7835 10月 26 21:32 test2.1
-rw-rw-r-- 1 lanyang lanyang 70 10月 26 21:21 tmp
会发现使用printf写到管道中的数据丢失了。这是因为printf带有缓冲区,标准输入重定向为管道写断后,变为全缓冲。printf的数据不会立刻放到管道中。
后面再执行exec,输出的数据会将前面的数据覆盖,于是管道中就不会有printf的数据了。这个地方如果使用write则会正常,因为write不带缓冲,直接写到管道中。如果带缓冲区的printf,则fflush一下。
命名管道:
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define FNAME "/tmp/TestFIFO"
int main()
{
char buffer[32] = {0};
//注意下面的0666
//4 2 1分别表示读、写和执行权限
//第一个6表示文件所有者具有读写权限
//第二个6表示同组用户权限
//地三个6表示其他用户读写权限
int mkRet = mkfifo(FNAME, 0666); //mkfifo的第一个参数必须是不存在的文件,执行第二次就会出错
if (mkRet == -1)
{
perror("mkfifo failed\n");
exit(1);
}
int pid = fork();
if (pid < 0) {
perror("fork error");
exit(1);
}
else if (pid == 0) //子进程
{
int fd = open(FNAME, O_RDONLY);
read(fd, buffer, sizeof(buffer)); //read会一直等待可读数据
printf("r content = %s\n", buffer);
close(fd);
}
else if (pid > 0)
{
// wait(NULL);
char s[] = "what a nice day!";
int fd = open(FNAME, O_WRONLY);
size_t len = sizeof(s);
printf("len = %d\n", len);
write(fd, s, sizeof(s));
printf("write over!\n");
close(fd);
}
return 0;
}
$ gcc -o fifo fifo.c
$ ./fifo
len = 17
write over!
r content = what a nice day!
第二次执行,则会出错。
$ ./fifo
mkfifo failed
: File exists
参考
http://blog.csdn.net/wutaozhao/article/details/6010665
http://blog.csdn.net/ljianhui/article/details/10202699
相关文章推荐
- Iptables 命令使用举例
- CBuilder中使用管道技术实例
- struts标签使用举例--logic篇
- Linux下进程的创建及其使用管道进行进程之间的通讯[00原创]
- java.util.regex.Pattern类使用举例
- 常用struts标签使用举例--logic篇
- 常用struts标签使用举例--html篇(转载)
- struts标签使用举例--logic篇
- Iptables 命令使用举例
- 在.NET程序中使用PIPE(管道技术)
- 匿名管道的使用,显示CMD命令行内容!
- 如何使用匿名管道输出重定向
- 使用easymock简单举例
- freebsd ports 使用举例:安装 mysql
- 在.NET程序中使用PIPE(管道技术)
- 命名管道的使用
- 在.NET程序中使用PIPE(管道技术)
- 常用struts标签使用举例--bean篇(转载)
- C#实现使用HTTP管道的.NET远程代码示例
- 使用DOS管道的代码片段