#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <fcntl.h> /* Definition of O_* constants */
#include <unistd.h>
int dup3(int oldfd, int newfd, int flags);
Example:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#define debug_log printf("%s:%s:%d--",__FILE__, __FUNCTION__, __LINE__);printf
int main(int argc, char **argv)
{
int ret = 0;
const char *buf1 = "hello my name is Carlos\n";
const char *buf2 = "this is the string 2\n";
const char *buf3 = "this is the string 3\n";
const char *buf4 = "this is the string 4\n";
const char *buf5 = "tfjfksdjflkdsjlkfjlksdjflkj\n";
int origin_fd = 4, fd2 = 5, fd3 = 6, fd4 = 7, fd5 = 8, origin_fd_1 = 9;
origin_fd = open("out_file.txt", O_RDWR|O_CREAT,0644);
if (origin_fd == -1) {
debug_log("origin_fd open failed, ret = %d\n", origin_fd);
goto exit;
}
origin_fd_1 = open("out_file_2.txt", O_RDWR|O_CREAT,0644);
if (origin_fd_1 == -1) {
debug_log("origin_fd open failed, ret = %d\n", origin_fd);
goto exit;
}
ret = write(origin_fd_1, buf1, strlen(buf1));
debug_log("origin_fd write %d bytes on the file, origin_fd = %d\n", ret, origin_fd);
// test dup, it is doesn't matter that close the original fd.
fd2 = dup(origin_fd_1); // dup doesn't close the original fd.
ret = write(fd2, buf2, strlen(buf2));
debug_log("fd2 write %d bytes on the file, fd2 = %d\n", ret, fd2);
ret = write(origin_fd, buf2, strlen(buf2));
debug_log("origin_fd write %d bytes on the file\n", ret);
// test dup2
fd4 = dup2(fd2, fd3); // dup2, fd3 is fd4
debug_log("fd2 = %d fd3 = %d, fd4 = %d\n", fd2, fd3, fd4);
ret = write(fd3, buf3, strlen(buf3));
debug_log("fd3 write %d bytes on the file\n", ret);
ret = write(fd4, buf4, strlen(buf4));
debug_log("fd4 write %d bytes on the file, fd3 = %d, fd4 = %d\n", ret, fd3, fd4);
ret = write(fd2, "using fd2 rewrite file", 22);
debug_log("fd2 write %d bytes on the file, fd2 = %d\n", ret, fd2);
// re-directing the stdin
fd5 = dup2(fileno(stdout), fd4);
ret = write(fd5, buf5, strlen(buf5));
debug_log("fd5 write %d bytes on the file, fd5 = %d\n", ret, fd5);
close(fd2);
close(fd3);
close(fd4);
close(fd5);
debug_log("test finish!");
exit:
return 0;
}
int test_pipe_rw_fork_dup()
{
int ret = 0;
int data_process = 0;
int file_pipes[2];
const char some_data[] = "hello world";
char buffer[BUFSIZ + 1];
pid_t pid = 0;
memset(buffer, '\0', sizeof buffer);
ret = pipe(file_pipes);
if (ret != 0) {
debug_log("pipe failed, ret = %d\n", ret);
goto exit;
}
pid = fork();
if (pid == -1) {
debug_log("fork failed, ret = %d\n", ret);
goto exit;
}
// child process
else if (pid == 0) {
// close STDIN
close(0);
// dup pipes[0] -> STDIN_FILENO
dup(file_pipes[0]);
close(file_pipes[0]);
close(file_pipes[1]);
execlp("od", "od", "-c", (char*) 0);
debug_log("child wrote the bytes\n");
}
// parent process
else {
close(file_pipes[0]);
data_process = write(file_pipes[1], some_data, strlen(some_data));
close(file_pipes[1]);
debug_log("parent write %d bytes: %s\n", data_process, some_data);
}
exit:
return ret;
}
输出:
# carlos @ Carloss-MBP in ~/workspace/work/clab/macos/test_pipe on git:master x [14:37:49]
$ ./test.elf
/Users/carlos/workspace/work/clab/macos/test_pipe/test_pipe.c:test_pipe_rw_fork_dup:161--parent write 11 bytes: hello world
0000000 h e l l o w o r l d
0000013
Linux进程之间的通信-管道(下)
1 dup和管道函数
1.1 dup
dup函数,复制文件句柄映射,fd2 = dup(fd1):
dup2函数,fd3 = dup2(fd1, fd2):
Note, std的文件描述符总是在使用最小可用的数字,例如,关闭掉std的文件描述符,那么文件描述符就会找到除了0以外最小的描述符。如下表格,如果我们close(0)之后,stdin的文件描述符被关闭,此时管道文件描述符使用stdin。
Example:
1.2 管道和dup
这里面可以利用fd的最小可用属性可以实现fork进程之间的stdout -> stdin管道通信。这里需要注意的是:
输出:
2 命名管道:FIFO
之前的管道我们可以叫做匿名管道,匿名管道有个比较重要的特点:两个进程之间必须有共同的祖先进程,也就是必须要fork或者exec才能完成管道之间的通信。为了打破这个限制,Linux提供了命名FIFO管道,允许两个毫无关系的进程相互通信,而且这种通信的传输速率还是很高的。我们在Linux命令行中可以轻易的使用命名管道FIFO。
2.1 shell中的命名管道
创建管道
$ mkfifo ./fifo
读入管道的内容
$ cat < ./fifo
此时cat命令被阻塞,因为没有任何的数据被写入管道。
写入管道内容
$ echo "Hallow world! > ./fifo"
此时在cat的命令终端就可以看到写入的数据了。
2.2 FIFO PIEP APIs
这里面的mode还是有个点说法的:
注意,在调用write和read函数对FIFO进行写读操作的时候,要注意对写进行“原子化”,每个写的长度保证小于等于PIPE_BUF(在limits.h文件中)字节,系统可以保证数据不会交错在一起,所以单次长度限制长度小于PIPE_BUF。
2.3 Example
实现两个进程之间使用FIFO管道交互:
Server : Write data
Client: Read data