Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 此代码中是否存在竞争条件的可能性?_C_Linux Kernel_Race Condition - Fatal编程技术网

C 此代码中是否存在竞争条件的可能性?

C 此代码中是否存在竞争条件的可能性?,c,linux-kernel,race-condition,C,Linux Kernel,Race Condition,我正在编程一个不应该同时访问的缓冲区。这有可能发生吗?该代码只是创建了一个缓冲区,许多程序将访问该缓冲区,该缓冲区充当FIFO队列。我使用的是我认为初始化良好的内核信号量。?我怎样才能尝试这个代码 #define MAX_BUFFER_SIZE 1024 #include "cbuffer.h" #include <linux/string.h> #include <asm-generic/uaccess.h> #include <asm-generic/errn

我正在编程一个不应该同时访问的缓冲区。这有可能发生吗?该代码只是创建了一个缓冲区,许多程序将访问该缓冲区,该缓冲区充当FIFO队列。我使用的是我认为初始化良好的内核信号量。?我怎样才能尝试这个代码

#define MAX_BUFFER_SIZE 1024

#include "cbuffer.h"
#include <linux/string.h>
#include <asm-generic/uaccess.h>
#include <asm-generic/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/semaphore.h>

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Driver Module for DSO");
MODULE_AUTHOR("Kaostias");

/*  
 *  Prototypes - this would normally go in a .h file
 */
int init_module(void);
void cleanup_module(void);
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);

#define SUCCESS 0
#define DEVICE_NAME "fifodev"   /* Dev name as it appears in /proc/devices   */
#define BUF_LEN 512         /* Max length of the message from the device */

/* 
 * Global variables are declared as static, so are global within the file. 
 */

static int Major;       /* Major number assigned to our device driver */
static int Device_Open = 0; /* Is device open?  
                 * Used to prevent multiple access to device */

cbuffer_t * buf;

struct semaphore prod_queue,cons_queue;
struct semaphore mtx;
int nr_prod_init, nr_cons_init;

int nr_prod_waiting,nr_cons_waiting;

int nr_producers,nr_consumers;
int nr_active_prod, nr_active_con;

static struct file_operations fops = {
    .read = device_read,
    .write = device_write,
    .open = device_open,
    .release = device_release
};

/*
 * This function is called when the module is loaded
 */
int init_module(void)
{
        Major = register_chrdev(0, DEVICE_NAME, &fops);

    if (Major < 0) {
      printk(KERN_ALERT "Registering char device failed with %d\n", Major);
      return -Major;
    }
    /*
     * Creation of buffer;
     */
    if( (buf = create_cbuffer_t(MAX_BUFFER_SIZE)) == NULL){
        printk(KERN_ALERT "Error when creating the FIFO device.");
        return -EINVAL;
    }
    sema_init(&prod_queue,0);
    sema_init(&cons_queue,0);
    sema_init(&mtx,1);
    nr_prod_waiting=0;
    nr_cons_waiting=0;

    nr_active_prod = 0;
    nr_active_con =0;

    nr_producers=0;
    nr_consumers=0;

    printk(KERN_INFO "Buffer created without error.\n");
    printk(KERN_INFO "I was assigned major number %d. To talk to\n", Major);
    printk(KERN_INFO "the driver, create a dev file with\n");
    printk(KERN_INFO "'mknod /dev/%s c %d 0'.\n", DEVICE_NAME, Major);
    printk(KERN_INFO "Try various minor numbers. Try to cat and echo to\n");
    printk(KERN_INFO "the device file.\n");
    printk(KERN_INFO "Remove the device file and module when done.\n");

    return SUCCESS;
}

/*
 * This function is called when the module is unloaded
 */
void cleanup_module(void)
{
    /* 
     * Unregister the device 
     */
    /*int ret = */unregister_chrdev(Major, DEVICE_NAME);
/*  if (ret < 0)
        printk(KERN_ALERT "Error in unregister_chrdev\n");//, ret);*/
    /*
     * Destroys the FIFO buffer
     */
    destroy_cbuffer_t (buf);

}

/*
 * Methods
 */

/* 
 * Called when a process tries to open the device file, like
 * "cat /dev/mycharfile"
 */
static int device_open(struct inode *inode, struct file *file)
{
    static int counter = 0;
    printk(KERN_ALERT "Entrando a Device_Open");

    if (down_interruptible(&mtx)) /*BLOQUEO*/
        return -EINTR;


    if (file->f_mode & FMODE_READ){
        nr_consumers++;
        while(nr_producers == 0){
            up(&mtx);
            /*Espera*/
            if (down_interruptible(&cons_queue)){
                down(&mtx);
                nr_consumers--;
                up(&mtx);       
                return -EINTR;
            }
            if (down_interruptible(&mtx))
                return -EINTR;
        }
        nr_active_prod++;
//      up(&mtx);
        if(nr_active_con == 0){

            up(&prod_queue);
        }

    } else {
        nr_producers++;
        while(nr_consumers == 0){
            up(&mtx);
            /*Espera*/
            if(down_interruptible(&prod_queue)){
                down(&mtx);
                nr_producers--;
                up(&mtx);
                return -EINTR;
            }
            if (down_interruptible(&mtx))
                return -EINTR;
        }
        nr_active_con++;
//      up(&mtx);

        if(nr_active_prod == 0){
            up(&cons_queue);
        }
    }

    Device_Open++;
    printk(KERN_ALERT "The device %s has been open %d times.\n",DEVICE_NAME ,++counter);
    try_module_get(THIS_MODULE);
    printk(KERN_ALERT "activos: Productores-%d; Consumidores-%d",nr_active_prod,nr_active_con);
    up(&mtx); /*Fin bloqueo*/

    printk(KERN_ALERT "Saliendo de device_Open");
    return SUCCESS;
}

/* 
 * Called when a process closes the device file.
 */
static int device_release(struct inode *inode, struct file *file)
{
    printk(KERN_ALERT "Entrando a device_release");

    if (down_interruptible(&mtx)){
        return -EINTR;
    }   /*BLOQUEO*/
    if (file->f_mode & FMODE_READ){
        nr_active_con--;
    }else{
        nr_active_prod--;
    }
    Device_Open--;      /* We're now ready for our next caller */
    printk(KERN_ALERT "hay %d dispositivos abiertos", Device_Open);
    module_put(THIS_MODULE);

    up(&mtx);  /*Fin bloqueo*/

    printk(KERN_ALERT "Saliendo de device_release");
    return SUCCESS;
}

/* 
 * Called when a process, which already opened the dev file, attempts to
 * read from it.
 */
static ssize_t device_read(struct file *filp,   /* see include/linux/fs.h   */
               char *buffer,    /* buffer to fill with data */
               size_t length,   /* length of the buffer     */
               loff_t * offset)
{
    char aux[BUF_LEN];
    printk(KERN_ALERT "Entrando a device_read");

    /*if (length > BUF_LEN) 
        return -EINVAL;*/
    /*BLOQUEO*/
    if (down_interruptible(&mtx)){
        return -EINTR;
    }

    if (nr_active_prod==0 && size_cbuffer_t(buf)<length){//is_empty_cbuffer_t(buf)){
        up(&mtx);
        return 0;
    }
    while(size_cbuffer_t(buf)<length){
        nr_cons_waiting++;
        printk(KERN_ALERT "Bloqueo sideral, cons: %d, prod: %d",nr_cons_waiting,nr_prod_waiting);
        printk (KERN_ALERT "Tam_buffer-%d, tamCadena-%d",size_cbuffer_t(buf),length);
        up(&mtx);

        /* Bloqueo en cola de espera */     
        if (down_interruptible(&cons_queue)){
            down(&mtx);
            nr_cons_waiting--;
            up(&mtx);       
            return -EINTR;
        }

    /* Readquisición del 'mutex' antes de entrar a la SC */     
        if (down_interruptible(&mtx)){
            return -EINTR;
        }
        if (nr_active_prod==0 && size_cbuffer_t(buf)<length){
            up(&mtx);
            return 0;
        }   

    }

    remove_items_cbuffer_t (buf,aux, length);//length);

    if (nr_prod_waiting>0){
        up(&prod_queue);    
        nr_prod_waiting--;
    }

    /* Salir de la sección crítica */   
    up(&mtx);
    /*Fin bloqueo*/
    if(copy_to_user(buffer, aux, length)){
        printk(KERN_ALERT "error en copy_to_user");
        return -EINVAL;
    }

    printk(KERN_ALERT "Saliendo de device_read");
    return length;
}

/*  
 * Called when a process writes to dev file: echo "hi" > /dev/hello 
 */
static ssize_t
device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
{
    char aux[BUF_LEN];
    printk(KERN_ALERT "Entrando a device_write");

    if (len>BUF_LEN){
        printk(KERN_ALERT "Error, la longitud del buffer es excesiva, es de %d", len);
        return -ENOSPC;
    }

    if(copy_from_user(aux,buff,len)){
        printk(KERN_ALERT "Problemas en copy from user");
        return -EFAULT;
    }
    /*BLOQUEO*/
    if (down_interruptible(&mtx)){
        printk(KERN_ALERT "Problemas en bloqueo");  
        return -EINTR;
    }

    if (nr_consumers==0){
        up(&mtx);
        return -EFAULT;
    }

    while(nr_gaps_cbuffer_t(buf)<len){

        /*Se aumenta el número de productores esperando 
          y se levanta el bloqueo*/
        nr_prod_waiting++;
        up(&mtx);
        /* Se ponea dormir el proceso hasta que alguien lo despierte
        */
        if (down_interruptible(&prod_queue)){
            printk(KERN_ALERT "Problemas en bloqueo2");
            down(&mtx);
            nr_prod_waiting--;
            up(&mtx);       
            return -EINTR;
        }
        /* Una vez se ha despertado, se bloquea de nuevo
           (bloqueo general)*/
        if (down_interruptible(&mtx)){
            return -EINTR;
        }

        if (nr_consumers==0){
            up(&mtx);
            return -EFAULT;
        }   
    }

    insert_items_cbuffer_t(buf, aux, len);

    /* Despertar a los productores bloqueados (si hay alguno) */
      if (nr_cons_waiting>0){
        up(&cons_queue);    
        nr_cons_waiting--;
      }

      up(&mtx); /*Fin bloqueo*/

    aux[len] = '\0';
    printk(KERN_ALERT "Saliendo de device_write, se han escrito %d bytes",len);
    return len;
}
#定义最大缓冲区大小1024
#包括“cbuffer.h”
#包括
#包括
#包括
#包括
#包括
#包括
#包括
模块许可证(“GPL”);
模块描述(“DSO驱动模块”);
模块作者(“Kaostias”);
/*  
*原型-这通常放在.h文件中
*/
int init_模块(void);
空洞清理模块(空洞);
静态int设备_打开(结构索引节点*,结构文件*);
静态int设备发布(结构索引节点*,结构文件*);
静态ssize\u t设备读取(结构文件*、字符*、大小\u t、loff\u t*);
静态ssize\u t设备写入(结构文件*,常量字符*,大小\u t,loff\u t*);
#定义成功0
#定义在/proc/devices中显示的设备名称“fifodev”/*Dev NAME*/
#定义来自设备的消息的BUF_LEN 512/*最大长度*/
/* 
*全局变量声明为静态变量,因此在文件中是全局变量。
*/
静态int-Major;/*分配给设备驱动程序的主要编号*/
静态int设备_Open=0;/*设备打开了吗?
*用于防止对设备的多次访问*/
cbuffer_t*buf;
结构信号量prod_队列、cons_队列;
结构信号量mtx;
内部生产初始值,初始值;
int nr_prod_waiting,nr_cons_waiting;
国际天然橡胶生产商、天然橡胶消费者;
int nr_active_prod,nr_active_con;
静态结构文件\u操作fops={
.read=设备读取,
.write=设备写入,
.open=设备\u打开,
.release=设备释放
};
/*
*加载模块时调用此函数
*/
int init_模块(void)
{
主要=寄存器\u chrdev(0,设备名称和fops);
如果(主要<0){
printk(KERN_警报“注册字符设备失败,错误为%d\n”,主要错误);
返回-主要;
}
/*
*创建缓冲区;
*/
if((buf=create\u cbuffer\u t(MAX\u BUFFER\u SIZE))==NULL){
printk(KERN_ALERT“创建FIFO设备时出错”);
返回-艾因瓦尔;
}
sema_init(&prod_队列,0);
sema_init(&cons_队列,0);
sema_init(&mtx,1);
nr_prod_waiting=0;
nr_cons_waiting=0;
nr_active_prod=0;
nr_活动_con=0;
nr_=0;
nr_=0;
printk(KERN_INFO“创建的缓冲区没有错误。\n”);
printk(KERN_INFO“我被分配给了%d个主修号以便与之交谈”,主修);
printk(KERN_INFO“驱动程序,使用\n创建一个开发文件”);
printk(内核信息“'mknod/dev/%s c%d 0”。\n”,设备名称,专业);
printk(KERN_INFO“尝试各种小数字。尝试cat并回显到\n”);
printk(KERN_INFO“设备文件”。\n”);
printk(KERN_INFO“完成后删除设备文件和模块。\n”);
回归成功;
}
/*
*卸载模块时调用此函数
*/
空洞清理_模块(空洞)
{
/* 
*注销设备
*/
/*int ret=*/unregister\u chrdev(主要设备名称);
/*如果(ret<0)
printk(KERN_ALERT“注销chrdev时出错”);/,ret)*/
/*
*销毁FIFO缓冲区
*/
销毁(buf);
}
/*
*方法
*/
/* 
*当进程试图打开设备文件时调用,如
*“cat/dev/mycharfile”
*/
静态int设备\u打开(结构索引节点*索引节点,结构文件*文件)
{
静态整数计数器=0;
printk(KERN_ALERT“Entrando a Device_Open”);
如果(向下可中断(&mtx))/*BLOQUEO*/
返回-EINTR;
if(文件->f_模式和FMODE_读取){
nr_消费者++;
while(nr_==0){
向上移动(&mtx);
/*埃斯佩拉*/
if(向下可中断(&cons_队列)){
下行(和mtx);
NRU消费者--;
向上移动(&mtx);
返回-EINTR;
}
if(向下可中断(&mtx))
返回-EINTR;
}
nr_active_prod++;
//向上移动(&mtx);
如果(nr\u active\u con==0){
启动(生产队列(&P);
}
}否则{
nr_++;
while(nr_消费者==0){
向上移动(&mtx);
/*埃斯佩拉*/
if(停机可中断(&prod_队列)){
下行(和mtx);
NRU生产商--;
向上移动(&mtx);
返回-EINTR;
}
if(向下可中断(&mtx))
返回-EINTR;
}
nr_active_con++;
//向上移动(&mtx);
如果(nr\U active\U prod==0){
向上(&cons_队列);
}
}
设备_Open++;
printk(KERN_ALERT“设备%s已打开%d次。\n”,设备名称,++计数器);
try_module_get(此_模块);
printk(内核警报“活动:生产商-%d;消费商-%d”,未激活产品,未激活控制);
向上(&mtx);/*Fin bloqueo*/
printk(KERN_ALERT“Saliendo de device_Open”);
回归成功;
}
/* 
*当进程关闭设备文件时调用。
*/
静态int设备发布(结构inode*inode,结构文件*file)
{
printk(KERN_ALERT“Entrando a device_release”);
if(向下可中断(&mtx)){
返回-EINTR;
}/*BLOQUEO*/
if(文件->f_模式和FMODE_读取){
nr_活动_con--;
}否则{
nr_活动_产品--;
}
设备_Open--;/*我们现在准备好迎接下一个来电*/
printk(内核警报“hay%d dispositivos abiertos”,设备打开);
模块输出(该模块);
向上(&mtx);/*Fin bloqueo*/
printk(KERN_ALERT“Saliendo de device_release”);
回归成功;
}
/* 
*当已打开dev文件的进程尝试
*读读它。
*/
静态ssize_t device_read(结构文件*filp,/*请参阅include/linux/fs.h*/
char*buffer,/*用数据填充的缓冲区*/
大小\u t长度,/*缓冲区的长度*/
loff_t*偏移量)
{
char aux[BUF_LEN];
printk(内核警报“进入设备”_