Solaris

父程序總是在子程序之後列印輸出

  • March 9, 2016

考慮在 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 提示不會交錯。

引用自:https://unix.stackexchange.com/questions/268708