Solaris
父程序總是在子程序之後列印輸出
考慮在 Solaris 11.3 下執行的以下程式碼:
int main(void) { pid_t pid = fork(); if (pid > 0) { printf("[%ld]: Writing from parent process\n", getpid()); } if (pid == 0) { execl("/usr/bin/cat", "/usr/bin/cat", "file.c", (char *) 0); perror("exec failed"); exit(1); } }
每當我執行它時,“從父級寫入”行總是最後輸出。如果我的學校任務不使用 wait(2) 以便僅在子程序完成後列印該行,我不會對這個結果感到驚訝。為什麼會發生這種情況以及如何確保在子程序執行 cat 之前列印此行(或至少未定義順序),所以我可以安全地使用 wait(2) 或 waitpid(2) 來解決這個問題?
正如@AndrewHenle 評論的那樣,根據系統以特定順序安排您的流程是不安全和不合理的。即使調度看起來是一致的(如您的情況),也沒有什麼能阻止作業系統的實現者改變調度程序的行為。
如果程序/執行緒之間的操作順序相關,則需要某種形式的通信。
對於您的場景,一個簡單的阻塞讀取就可以完成這項工作。在叉子之前創建一個管道。然後僅在父級列印其消息後才從父級寫入管道。同時,孩子從管道中讀取的嘗試將阻止其執行,直到父母寫入。
忽略每個程序中的錯誤處理和未使用的管道文件描述符(通常在分叉後顯式關閉):
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> int main(void) { char buf[1]; int pipe_fds[2]; pipe(pipe_fds); pid_t pid = fork(); if (pid > 0) { printf("[%ld]: Writing from parent process\n", getpid()); write(pipe_fds[1], "_", 1); wait(NULL); } if (pid == 0) { read (pipe_fds[0], buf, 1); execl("/usr/bin/cat", "/usr/bin/cat", "file.c", (char *) 0); perror("exec failed"); exit(1); }
您可能應該在父級中使用 wait ,這樣如果它是從終端執行的,則子級的輸出和 shell 提示不會交錯。