[英]Why can't I write to or read from pipes?
我已經看到了很多類似的問題,但是所有這些問題都針對特定的情況,因此沒有幫助我找到解決方案。 對於我的情況,請提供以下反饋:
我正在嘗試編寫一個程序來從文本文件中獲取字符數。 該程序通過派生四個映射器和26個reducer並為它們中的每個創建管道來工作。 父進程將輸入分為四行,然后將其傳遞給每個映射器,該映射器計算其行中每個字符的數量。 然后,每個映射器將計數傳遞到適當的縮減器,后者對所有四個計數求和並打印結果。
以下是到目前為止的代碼:
int main(int argc, char *argv[])
{
int i = 0;
FILE *input = fopen("input.txt", "r");
// Things for reading line-by-line: see getline reference on man7.org
char *line = NULL;
size_t len = 0;
// Where we'll store the messages
static char message[MSGSIZE];
for(i = 0; i < NUMREDUCERS; i++)
{
pipe(reducer_pipes[i]);
}
for(i = 0; i < NUMMAPS; i++)
{
// Step 1: Create pipes for communication using the system call pipe()
pipe(mapper_pipes[i]);
// Step 2: Fork a number of mappers (4).
if (fork() == 0)
{
// Don't want to close the write pipe yet
// Child process: one of the mappers
read(mapper_pipes[i][0], message, MSGSIZE); // Read from reading end
char *msg = "Error reading from pipe";
check_errors(msg);
// Get char count and write to pipe
int j = 0;
int ccount = 0;
for(j = 0; j < NUMREDUCERS; j++)
{
// Count up the number of chars
ccount = count_char(message, (char) (j + 97), MSGSIZE);
// Write to the appropriate reducer pipe
write(reducer_pipes[j][1], (char *) ccount, MSGSIZE);
msg = "error writing to reducer pipe";
check_errors(msg);
}
exit(EXIT_SUCCESS);
}
else
{
getline(&line, &len, input);
// Parent process
write(mapper_pipes[i][1], line, (int) len);
char *msg = "Error writing to pipe";
check_errors(msg);
}
}
return 0;
}
我遇到的問題是我無法寫入減速器管道。 每當我嘗試寫入,讀取或關閉它們時,我都會收到一個錯誤的地址錯誤。 他們以某種方式到期了嗎? 我沒有正確創建它們嗎? 如果有人願意提供意見,我將不勝感激。
快速編輯:我刪除了所有“關閉”語句,因為它們都存在相同的問題。 但是,我嘗試關閉應該關閉管道的位置,只是找到了相同的錯誤消息。
“地址errno == EFAULT
”( errno == EFAULT
)表示您已將無效指針傳遞給系統調用。 從本質上講,它相當於一個段錯誤(我相信某些系統實際上在這種情況下會提高SIGSEGV
)。
看這行:
write(reducer_pipes[j][1], (char *) ccount, MSGSIZE);
這里的ccount
是int類型的。 將int轉換為指針始終是可疑的。
在上一行中,您ccount
分配給count_char()
的返回值。 現在您沒有向我們展示該函數的代碼,但是我想它會返回一個字符數-最有可能是一個小整數。 假設它返回了17。您正在告訴write
寫入位於地址17的MSGSIZE
字節。這肯定不是您想要的。
如果您想以二進制格式將該整數發送給reducer,您可能想說
write(reducer_pipes[j][1], &ccount, sizeof(ccount));
當然,您必須在減速器端具有匹配的代碼。
其他人已經解決了代碼中的許多其他問題,例如您僅通過查看errno
就無法可靠地檢測錯誤(這大概就是check_errors
所做的事情)。 如果系統調用沒有錯誤,則即使先前具有非零值,也不會errno
。 相反,您應該做的是檢查write()
的返回值; 如果它是-1
那么將發生錯誤,只有這樣,您才應該查看errno
(或致電perror
)以查看其含義。
基本上,每當您進行系統調用並且不檢查返回值時,都會遇到錯誤。
您沒有顯示您的check_errors
函數是什么,但是我猜想它只是在顯示錯誤消息而沒有實際檢查錯誤的情況下,假設您僅在發生錯誤后才調用它。 因此,您實際上可能並沒有收到錯誤消息。
您實際上需要檢查讀寫調用的返回值,以查看是否發生錯誤:
if ((len = read(mapper_pipes[i][0], message, MSGSIZE)) < 0) // Read from reading end
perror("Error reading from pipe");
請注意,如果沒有錯誤,返回值還會告訴您接收到的消息的長度(您應該在查看該消息的后續代碼中使用該值代替MSGSIZE
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.