全是~!
在linux系统中,共享数据应该是互斥的。并且,该数据在内核空间和用户空间之间通过mmap共享。所以我按下面的程序编程了。
/用户空间
void access_shared_data_user(void)
{
//snip..
ioctl(test_fd, IOCTL_DOWN_SEM);
shared_data++;
//some access to shared_data
ioctl(test_fd, IOCTL_UP_SEM);
}</核空间
static DEFINE_SEMAPHORE(test_sem);
static long test_ioctl(struct file *file, unsigned int cmd, unsigned long arg)<br>
{
//snip..
switch(cmd)
{
case IOCTL_DOWN_SEM:
down(&test_sem);
break;
case IOCTL_UP_SEM:
up(&test_sem);
break;
//snip..
}
void access_shared_data_kernel(void)
{
//snip..
down(&test_sem);
shared_data++;
//some access to shared_data
up(&test_sem);
}如我所料,上面的程序运行得很好,并且共享数据不受许多线程的保护。
顺便说一句,上面的程序有问题。如果在原子上下文(如IRQ处理程序)中调用access_shared_data_kernel,则该程序可能会发生死锁,因为信号量使用睡眠等待方法。
因此,我尝试使用自旋锁(Spin_lock_irqsave),但似乎没有办法在用户空间中使用自旋锁。
问:在原子上下文中,用户和内核之间是否有共享数据的解决方案?
发布于 2013-09-06 13:39:37
如果您要做的只是增量或递减,或者以其他方式修改单个整数类型值,则可以使用锁定操作。在内核中使用atomic_t,在用户模式应用程序中使用atmoic建筑应该很好。
显然,如果您需要做更复杂的事情,例如strcpy或字符串中的“用B替换所有A”,修改二叉树或其他“不容易变成单个操作”的工作,那么解决方案就是使用信号量。但是,正如您所说的,这将无法从IRQ (或其他一些情况下,调度程序是“锁定”)。
此外,您也不希望“在IRQ中等待用户模式来重新平衡树”。
我不认为有任何简单的解决办法来解决这个从IRQ -基本上,你不应该这样做。您可以在IRQ中使用down_trylock -这不会导致您的IRQ睡眠,如果信号量不可用,如果成功获得锁,则返回0,如果锁已经被其他东西持有,则返回非零。
现在,棘手的部分当然是“如果锁是不可用的,你会做什么”-我不能给出一个正确的答案,你的具体情况。典型的解决方案是将一个工作项排队,并在以后处理它。
编辑:执行“工作人员队列和以后的进程”的标准方法是使用tasklet
发布于 2013-09-09 02:21:45
亲爱的马茨,
谢谢你的回答。
我认为,down_trylock是修复我的程序的最佳解决方案。
实际上,在调用原子conterxt的情况下,我无条件地尝试返回access_shared_data_kernel函数中的fail。
但是当我使用down_trylock时,它不需要无条件返回,而且效率更高。
所以,我修改了代码如下。
void access_shared_data_kernel(void)
{
//狙击。
if(down_trylock(&mmclog_sem)){
如果(in_atomic()\x{e 010}\\x{
printk(“未能在原子上下文中获取信号量.!\n”);
return -1;
}
否则
下降(&mmclog_sem);
}
shared_data++;
//对shared_data的某些访问
up(&test_sem);
}
谢谢马茨,
https://stackoverflow.com/questions/18656533
复制相似问题