【发布时间】:2020-05-31 00:49:05
【问题描述】:
我正在为单个进程创建三个 FIFO 管道,其中多个写入器线程写入单个读取器线程。目标是为每个写入器线程创建一个单独的文件描述符,并为每个写入器文件描述符提供一个相应的读取器文件描述符,以便我知道哪个写入器线程属于每个记录。我的设置适用于所有编写器线程之间共享的一个编写器文件描述符和一个读取器文件描述符。
多读取器/写入器设置成功地设置了三个写入器 fd(6、7、8)和三个读取器 fd(9、10 和 11)。所有写入器线程成功发送数据,但读取器 fds 未成功读取数据(返回读取的零字节)。
当我在写入端打开 fd 时,我收到错误消息“打开:错误的文件描述符”,但它仍然返回一个唯一的 fd,并且该 fd 已成功用于写入,但未用于读取。
我在一个循环中从 NASM 调用 C 程序,每个编写器线程一次迭代:
xor r12,r12
mov r13,[Number_Of_Cores_Calc]
Setup_pipe:
lea rdi,[fifo_base_name]
mov rax,r12
add rax,48
mov byte[rdi+11],al
call fifo_delete wrt ..plt
call fifo_setup wrt ..plt
push rdi
call fifo_close wrt ..plt
pop rdi
Open_FIFO_Write:
mov rsi,1
call fifo_open wrt ..plt
lea rbp,[fifo_write_fds]
mov [rbp+r12*8],rax
add r12,1
cmp r12,r13
jl Setup_pipe
对应的C程序:
int64_t fifo_setup(char * fifo_name)
{
remove(fifo_name);
if (mkfifo(fifo_name, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) == -1) {
perror("mkfifo");
exit(EXIT_FAILURE); }
return 0;
}
int64_t fifo_open(char * fifo_name, int64_t read_write) {
int c;
if (read_write == 1) {
c = open(fifo_name, O_CREAT | O_RDWR);} //O_WRONLY
if (read_write == 2) {
c = open(fifo_name, O_CREAT | O_RDWR);} //O_RDONLY
perror("open");
return (c);
}
int64_t fifo_read(int fd, void *buf, size_t count) {
int status_read = read(fd, buf, count);
return status_read;
}
int64_t fifo_write(int fd, const void *buf, size_t count) {
int status_write = write(fd, buf, count);
return status_write; }
int64_t fifo_close(int fifo_fdes) {
close(fifo_fdes);
return 0; }
// Delete pre-existing file
int64_t fifo_delete(char * fifo_name) {
if( access( fifo_name, F_OK ) != -1 ) {
if (remove(fifo_name) == 0)
printf("File deleted successfully");
else
printf("Unable to delete the file");
}
return 0; }
所以我的问题是:
是否可以在写入端和读取端为每个线程使用单独的 fd 从多个线程写入单个读取器线程?
如果可以,我在上面做错了什么——尤其是为什么我得到“打开:错误的文件描述符”,但我仍然得到看起来像一个有效的文件描述符。
如果我不能使用 POSIX FIFO,我可以使用哪些 IPC 方法,以便每个写入线程在写入端和读取端都有自己唯一的 fd?数据报套接字?
感谢您对此的任何帮助。
【问题讨论】:
-
这没有意义。
open(2)不能返回EBADF,只能返回openat(2)。如果c是一个正数,那么您看到的是之前的errno值或其他值。 -
花絮:不要使用
access()!这适用于专门的 setuid/setgid 应用程序来确定 基础 用户是否能够访问该文件,这绝对不是一个方便的花花公子“文件是否存在?”功能。请改用stat()来检查是否存在。 -
不要无条件拨打
perror();仅当返回值指示错误时才调用它。与errno类似;除非调用的函数指示错误,否则不要对其进行测试。 -
O_CREAT标志似乎没有意义。有了它,如果您尝试打开的 fifo 不存在,您将创建一个具有相同名称的常规文件。此外,由于您没有将第三个参数传递给open(),因此该文件将获得随机权限。 -
一般建议:修复缩进和支撑位置。就目前而言,很难阅读;我不知道任何常见的 C 格式样式,其中块的右大括号与其最后一条语句位于同一行。
标签: c linux pipe named-pipes fifo