Arch-Linux

競爭條件在 Arch Linux 上不起作用

  • April 22, 2017

以下 C 程序應該說明黑白子程序和父程序的競爭條件:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main()
{
    fork();
    printf("\n 1234567890 \n");
    return 0;
}

當我的朋友(在Ubuntu上)執行它時,他們得到了預期的輸出,這是混亂的 1234567890s

一個例子:12312345645678907890

但是當我在我的Arch Linux上嘗試相同的程序時,它從來沒有給出這樣的輸出。它總是一個接一個。

1234567890 

1234567890 

我喜歡Arch linux是如何避免競爭條件的,但我想禁用任何此類功能,並希望得到我朋友的輸出。

printf呼叫將執行一個或多個write(2)系統呼叫,它們的處理順序將是輸出的實際順序。一個或多個,因為它取決於 C 庫內部的緩衝。使用行緩衝輸出(到終端),您可能會收到兩個write呼叫,一個用於初始換行符,另一個用於其餘的。

write(1, "\n", 1);
write(1, " 1234567890 \n", 13);

可以在呼叫之間安排另一個程序,首先給出兩個空行,然後是帶有數字的行,但鑑於沒有太多的處理正在進行,這在解除安裝的系統上不太可能。

請注意,由於兩個程序都列印完全相同的內容,因此哪個程序先執行並不重要,只要一個程序不打斷另一個程序即可。

如果輸出到文件或管道,預設情況下是完全緩衝的,所以你可能只會得到一個write呼叫(每個程序),並且沒有混合輸出的機會。

如果數字通過單獨的系統呼叫一個接一個地輸出,那麼您的混合數字範例將是可能的。很難理解為什麼一個明智的庫實現會在列印長度已知的靜態字元串時這樣做。隨著循環中的更多寫入,混合輸出的可能性更大:

像這樣的東西:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    int i;
    setbuf(stdout, NULL);  /* explicitly unbuffered */
    int x = fork(); 
    for (i = 0 ; i < 500 ; i++) {
         printf("%d", !!x);
    }
    if (x) {
         wait(NULL);  
         printf("\n");  
    }  
    return 0;  
}

給我如下輸出。大多數時候,並非總是如此。由系統決定如何安排程序。不可預測性是我們通常試圖避免競爭條件的原因。

111111111111111111111111111111111111111111111111111111111111111111111111111
111111111111111111111111111111111111111111111111111111111111111111111111111
111100000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000010000001001100
110000000011001100110011000000010011001100110000000100110011001100000001001
100110011000000010011001100110000000100110011001100000001001100110011000000
...

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