我已经编写了一个内核模块,它是一个字符设备驱动程序,类似于this 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);
是否存在数据竞赛或类似的事情?
答案 0 :(得分:1)
您的channelData
结构不能保证与缓存对齐,因此,除非您明确同步chData
,否则您仍然会遇到数据争用的情况。
这是比赛的草图:
在这种情况下,这几个字节在CPU 0上已过时,因为它们被CPU 1覆盖,而CPU 0却不知道。
它不知道,因为没有memory barrier告诉它它的缓存可能是陈旧的。
现在,在许多情况下,系统调用会触发内存屏障,但不能保证。
您的用户空间程序很好,字符设备是与内核模块进行通信的规范方式,但是您的内核模块必须正确同步。甚至您链接中的示例似乎也非常入门,并且在不使用原子的情况下进行了Device_Open++
之类的事情。