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

Linux kernel 内核编程中互斥和阻塞IO之间的区别?,linux-kernel,operating-system,mutex,semaphore,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(maxbyt

我无法理解以下两种代码之间的区别。任何主体都可以解释以下代码之间的差异吗?还可以用示例解释信号量和互斥量之间的差异

互斥:

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;
}
DEFINE_信号量(mysem);
静态ssize_t dev_read(结构文件*文件,字符*buf,大小lbuf,loff_t*ppos)
{
int maxbytes,bytes_to_do,nbytes;
maxbytes=大小-*ppos;
如果(maxbytes
阻塞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;
}
init_MUTEX_LOCKED(&mysem);
静态ssize_t dev_read(结构文件*文件,字符*buf,大小lbuf,loff_t*ppos)
{
int maxbytes,bytes_to_do,nbytes;
maxbytes=大小-*ppos;
如果(maxbytes
互斥体只是一个二进制信号量。这意味着互斥只能有两种状态:锁定和解锁。但信号量可以有两个以上的计数。因此,可以获取信号量锁的进程数等于初始化信号量的计数

在您的示例中,在第一个代码段中,无论是读还是写,无论哪个获取锁,都是在完成相应的读或写之后释放锁。由于互斥,两者不能同时工作


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

区别在于,第二个代码存在严重的错误,无法编译。它来自哪里?使用静态结构信号量mysem=\uu信号量\u初始值设定项(mysem,0)而不是init\u互斥锁(&mysem)