[英]C fifo keeps blocked
我目前正在研究使用C的多線程,但是對於我們命名的管道exersize,有些事情我不太了解。
我們期望實現文件搜索系統的實現,該系統查找文件並使用一個進程將其添加到緩沖區中,而第二個進程應從第一個進程的線程中獲取文件名,在該文件中查找搜索查詢,然后通過以下方式將位置返回給第一個進程管。 我幾乎完成了所有工作,但是我很困惑如何在兩個流程之間進行通信。
這是我進行通訊的代碼:
main.c
void *controller_thread(void *arg) {
pthread_mutex_lock(&index_mutex);
int index = t_index++; /*Get an index to thread*/
pthread_mutex_unlock(&index_mutex);
char sendPipe[10];
char recvPipe[10];
int fdsend, fdrecv;
sprintf(sendPipe, "contrl%d", (index+1));
sprintf(recvPipe, "minion%d", (index+1));
mkfifo(sendPipe, 0666);
execlp("minion", "minion", sendPipe, recvPipe, (char*) NULL);
if((fdsend = open(sendPipe, O_WRONLY|O_CREAT)) < 0)
perror("Error opening pipe");
if((fdrecv = open(recvPipe, O_RDONLY)) < 0)
perror("Error opening pipe");
while(1) {
char *fileName = pop(); /*Counting semaphore from buffer*/
if(notFile(fileName))
break;
write(fdsend, fileName, strlen(fileName));
write(fdsend, search, strlen(search));
char place[10];
while(1) {
read(fdrecv, place, 10);
if(notPlace(place)) /*Only checks if all numeric*/
break;
printf("Minion %d searching %s in %s, found at %s\n", index,
search, fileName, place);
}
}
}
從我發現的在線資源中,我認為這是在主機內部處理fifo的方法。 我試圖編寫一個測試仆從來確保它能正常工作,所以在這里
奴才
int main(int argc, char **argv) {
char *recvPipe = argv[1];
char *sendPipe = argv[2];
char fileName[100];
int fdsend, fdrecv;
return 0;
fdrecv = open(recvPipe, O_RDONLY);
mkfifo(sendPipe, 0666);
fdsend = open(sendPipe, O_WRONLY|O_CREAT);
while(1) {
read(fdrecv, fileName, 100);
write(fdsend, "12345", 6);
write(fds, "xxx", 4);
}
return 0;
}
當我以這種方式運行時,如果我將O_NONBLOCK更改為open模式,線程將被阻塞並且不輸出任何響應。 然后它會顯示“錯誤,打開沒有此類設備或地址的管道錯誤”錯誤,所以我知道我無法以某種方式在minion中打開recvPipe,但我不知道這是什么錯誤
您的代碼存在的問題之一是對execlp()
用法的明顯誤解。 成功后, 此函數不會返回 ,因此將永遠不會執行其后的代碼。 通常,首先是fork()
,然后在子進程中執行execlp()
,如果execlp()
失敗,則一定會使子終止。 父進程可能最終也需要等待派生的孩子。
另外,每個進程嘗試打開FIFO的寫端時都會通過O_CREAT
標志,這很奇怪,並且可能是不希望的。 這是不必要的,因為每個人都剛剛使用mkfifo()
創建了FIFO。 即使在mkfifo()
失敗或其他進程將其打開之前將其刪除的情況下,您也不想使用O_CREAT
打開,因為這將使您獲得常規文件,而不是FIFO。
解決execlp()
問題后,您還將遇到競爭狀況。 父進程依靠子進程創建一個FIFO,但是不等待該進程這樣做。 如果父項在孩子完成其mkfifo()
之前進行了打開嘗試,則您將不會獲得預期的行為。
我建議讓父進程在創建子進程之前創建兩個 FIFO。 孩子和父母必須通過打開一個FIFO的兩端進行合作,然后再打開另一個FIFO的兩端。 一個開放供讀取將阻塞,直到另一個開放相同的FIFO進行寫入。
或者,您可以使用普通(匿名)管道(請參閱pipe()
)代替FIFO。 它們在兩端都是開放式創建的,它們對於通過繼承關聯的流程之間的通信更為自然。
無論如何,請務必檢查函數調用的返回值 。 幾乎所有這些功能都可能失敗,並且比在您錯誤地假設每個調用成功的情況下理清可能形成的糾結要好得多,因此預先檢測並處理該問題要好得多。
Fifos需要在開放時間進行一些同步。 默認情況下,open(一個或多個)處於阻塞狀態,以便阻塞一個可讀的讀取,直到其他一些打開相同的fifo進行讀取,然后進行相反操作(此操作可使同級進行同步以進行通信)。 您可以使用O_NONBLOCK
在沒有實際的打開對等體的情況下打開進行讀取,但反之則為false,因為在沒有讀取對等體的情況下進行寫操作會導致錯誤(考慮在沒有讀取器的情況下嘗試寫入的過程)毫無意義)。
例如,您可以閱讀Linux Fifo手冊 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.