我正在寫一個程序,當從兩個單獨的bash會話作爲兩個單獨的進程運行時,打開兩個之間的命名管道以允許將字符串從一個發送到另一個。stat()爲什麼返回EFAULT?
當從一個終端首次執行進程時,它會檢查stat(fname, buf) == -1
以查看路徑fname
上的文件是否存在,如果不存在,則創建它。然後該過程假定由於它是製作FIFO
的那個,它將通過它發送消息並相應地繼續。
之後,程序可以從另一個終端運行,該終端應該通過檢查stat(fname, buf) == -1
來確定它將成爲通過管道的消息的接收方。現在條件應該返回false,並且stat(fname, buf)
本身應該返回0
,因爲現在在fname
處存在文件。
但由於我無法辨別的原因,當第二個過程運行時,stat(fname, buf)
仍然返回-1
。變量errno
設置爲EFAULT
。 stat()
的man
頁僅將EFAULT
描述爲「不良地址」。任何幫助確定錯誤發生的原因或「錯誤地址」的含義。將非常感激。
我已驗證該文件確實是按照預期由第一個進程創建的。第一個進程等待在行pipe = open(fname, O_WRONLY);
,因爲它不能繼續,直到打開pipe
的另一端。
編輯:以下是我的代碼的獨立實現。我已經確認它編譯和體驗了我在這裏描述的問題。
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define MAX_LINE 80
#define oops(m,x) { perror(m); exit(x); }
int main(int argc, char const *argv[]) {
char line[MAX_LINE];
int pipe, pitcher, catcher, initPitcher, quit;
struct stat* buf;
char* fname = "/tmp/absFIFOO";
initPitcher = catcher = pitcher = quit = 0;
while (!quit) {
if (((!pitcher && !catcher && stat(fname, buf) == -1) || pitcher) && !quit) {
// Then file does not exist
if (errno == ENOENT) {
// printf("We're in the file does not exist part\n");
if (!pitcher && !catcher) {
// Then this must be the first time we're running the program. This process will take care of the unlink().
initPitcher = 1;
int stat;
if (stat = mkfifo(fname, 0600) < 0)
oops("Cannot make FIFO", stat);
}
pitcher = 1;
// open a named pipe
pipe = open(fname, O_WRONLY);
printf("Enter line: ");
fgets(line, MAX_LINE, stdin);
if (!strcmp(line, "quit\n")) {
quit = 1;
}
// actually write out the data and close the pipe
write(pipe, line, strlen(line));
close(pipe);
}
} else if (((!pitcher && !catcher) || catcher) && !quit) {
// The first condition is just a check to see if this is the first time we've run the program. We could check if stat(...) == 0, but that would be unnecessary
catcher = 1;
pipe = open("/tmp/absFIFO", O_RDONLY);
// set the mode to blocking (note '~')
int flags;
flags &= ~O_NONBLOCK;
fcntl(pipe, F_SETFL, flags); //what does this do?
// read the data from the pipe
read(pipe, line, MAX_LINE);
if (!strcmp(line, "quit\n")) {
quit = 1;
}
printf("Received line: %s\n", line);
// close the pipe
close(pipe);
}
}
if (initPitcher)
unlink(fname);
return 0;
}
顯示有問題的代碼,最好是在[SSCCE](http://www.sscce.org)。這聽起來不像是需要很多代碼來重現。 – WhozCraig
EFAULT很可能意味着'fname'或'buf'是無效的指針。 – Art
此外使用'stat'這種方式並不是檢查文件是否存在的好方法。你打開自己最多[TOCTOU](http://en.wikipedia.org/wiki/Time_of_check_to_time_of_use)比賽。 – Art