内核编程中互斥和阻塞IO之间的区别?

时间:2013-10-04 07:17:11

标签: linux-kernel operating-system mutex semaphore

我无法理解以下两个代码之间的区别。任何机构都可以解释以下代码与之间的区别吗?还用例子解释了信号量和互斥量之间的差异....

相互排斥:

DEFINE_SEMAPHORE(mysem);
static ssize_t dev_read(struct file *file,char *buf, size_t lbuf, loff_t *ppos)
{
    int maxbytes, bytes_to_do, nbytes;
    maxbytes = SIZE - *ppos;
    if(maxbytes < lbuf) bytes_to_do = maxbytes;
    else bytes_to_do = lbuf;
    if(bytes_to_do == 0){
        printk("reached end of device\n");
        return -ENOSPC;
    }
    if(down_interruptible(&mysem))
        return -ERESTARTSYS;
    nbytes = bytes_to_do - copy_to_user(buf,dev_buf+*ppos,bytes_to_do);
    up(&mysem);
    *ppos += nbytes;
    return nbytes;
}
static ssize_t dev_write(struct file *file,const char *buf, size_t lbuf, 
                            loff_t *ppos)
{
    int maxbytes, bytes_to_do, nbytes;
    maxbytes = SIZE - *ppos;
    if(maxbytes < lbuf) bytes_to_do = maxbytes;
    else bytes_to_do = lbuf;
    if(bytes_to_do == 0){
        printk("reached end of device\n");
        return -ENOSPC;
    }
    if(down_interruptible(&mysem))
        return -ERESTARTSYS;
    nbytes = bytes_to_do - copy_from_user(dev_buf+*ppos,buf,bytes_to_do);
    ssleep(10);
    up(&mysem);
    *ppos += nbytes;
    return nbytes;
}

阻止IO

init_MUTEX_LOCKED(&mysem);
static ssize_t dev_read(struct file *file,char *buf, size_t lbuf, loff_t *ppos)
{
    int maxbytes, bytes_to_do, nbytes;
    maxbytes = SIZE - *ppos;
    if(maxbytes < lbuf) bytes_to_do = maxbytes;
    else bytes_to_do = lbuf;
    if(bytes_to_do == 0){
        printk("reached end of device\n");
        return -ENOSPC;
    }
    if(down_interruptible(&mysem))
        return -ERESTARTSYS;
    nbytes = bytes_to_do - copy_to_user(buf,dev_buf+*ppos,bytes_to_do);
    *ppos += nbytes;
    return nbytes;
}
static ssize_t dev_write(struct file *file,const char *buf, size_t lbuf, 
                            loff_t *ppos)
{
    int maxbytes, bytes_to_do, nbytes;
    maxbytes = SIZE - *ppos;
    if(maxbytes < lbuf) bytes_to_do = maxbytes;
    else bytes_to_do = lbuf;
    if(bytes_to_do == 0){
        printk("reached end of device\n");
        return -ENOSPC;
    }
    nbytes = bytes_to_do - copy_from_user(dev_buf+*ppos,buf,bytes_to_do);
    ssleep(10);
    up(&mysem);
    *ppos += nbytes;
    return nbytes;
}

1 个答案:

答案 0 :(得分:2)

Mutex只不过是一个二进制信号量。这意味着互斥锁只能有两种状态:锁定和解锁。但信号量可以有两个以上的数量。因此,可以获取信号量锁的进程数等于信号量初始化的计数。

在您的示例中,在第一个代码段中,无论是读取还是写入,获取锁定的任何一个本身也会在完成相应的读取或写入后释放锁定。由于互斥锁,两者都无法同时工作。

在第二个代码片段中,代码展示了阻塞I / O概念,旨在解决Linux设备驱动程序(LDD)一书中解释的问题:“当没有数据尚未读取时该怎么办,但我们”不是在文件结束。默认答案是进入睡眠等待数据“。正如您在代码中看到的那样,lock被声明为Mutex并且也处于锁定状态。因此,如果在没有数据时进行任何读取,则由于互斥锁已处于锁定状态,因此无法获取锁定,因此它将进入休眠状态(简短读取被阻止)。无论何时写入,它首先写入设备然后释放互斥锁。因此,现在阻塞读取可以获取该锁定并可以完成其读取过程。在这里,两者都不能同时工作,但是锁定获取和释放机制是以这样的方式同步的,即在写入不向设备写入任何内容之前读取不能进行。