簡體   English   中英

系統調用是線程安全的嗎?

[英]Are system calls thread-safe?

我寫了一個內核模塊,它是一個類似於Link的字符設備驅動程序。驅動程序具有如下內部結構:

struct {
    str[500];
}channelData;

static channelData chData[4];

所以我有一個使用這個驅動程序的多線程應用程序,我目前以下列方式使用這個驅動程序:

typedef struct
{
        int channelId;
        int len;
        char arg[100];
} driverArgs;

class DevDrv{
    static void STR_READ(int channelId, char *data);
    static void STR_SEND(int channelId, char *data,int len);
};

void DevDrv::STR_READ(int channelId, char *data)
{
    driverArgs arg= {-1,0, {0}};
    arg.channelId = channelId;
    ioctl(mfilehandler,IOCTL_STR_READ,&arg);
    memcpy(data,arg.arg,arg.len)

}
void DevDrv::STR_SEND(int channelId, char *data,int len)
{
    driverArgs arg= {-1,0, {0}};
    arg.channelId = channelId;
    arg.len=len;
    memcpy(arg.arg,data,len);
    ioctl(mfilehandler,IOCTL_STR_SEND,&arg);
}

所以,問題是我的應用程序中的 4 個線程是否調用這些函數來讀取或寫入他們自己的 ChannelId 像這樣讀取或寫入驅動程序:

thread1:
   DevDrv::STR_READ(0,&localdst);
thread2:
   DevDrv::STR_READ(1,&localdst);
thread3:
   DevDrv::STR_READ(2,&localdst);
thread4:
   DevDrv::STR_READ(3,&localdst);

是否有數據競賽或類似的事情發生?

您的channelData結構不能保證緩存對齊,因此除非您明確同步chData ,否則您仍然會受到數據chData

這是一場比賽的草圖:

  1. 系統調用想要讀入 CPU 0 上的通道 2。
  2. CPU 0 獲取包含通道 2 的所有緩存行,這意味着:
    • 通道 2 中的所有字節
    • 距離通道 1 末尾的幾個字節
    • 從通道 3 開始的幾個字節
  3. 閱讀照常進行。
  4. CPU 1 將 500 字節寫入通道 1。
  5. 系統調用想要將 500 個字節讀入 CPU 0 上的通道 1。
  6. CPU 0 從通道 1 中獲取之前未獲取的所有字節。
    • 通道 1 末尾的幾個字節不會重新獲取

在這種情況下,這幾個字節在 CPU 0 上是陳舊的,因為它們被 CPU 1 覆蓋,而 CPU 0 不知道。

它不知道,因為沒有內存屏障告訴它它的緩存可能已經過時。

現在,在許多情況下,系統調用會觸發內存屏障,但不能保證。

您的用戶空間程序很好,字符設備是與內核模塊通信的規范方式,但您的內核模塊必須正確同步。 甚至您鏈接中的示例似乎也試圖非常具有介紹性,並且在不使用原子的情況下執行Device_Open++類的操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM