gpt4 book ai didi

c - 这段代码中是否存在竞争条件的可能性?

转载 作者:行者123 更新时间:2023-11-30 15:40:13 25 4
gpt4 key购买 nike

我正在编写一个不应同时访问的缓冲区。有没有可能发生这种情况?该代码只是创建一个缓冲区,该缓冲区将被许多程序访问并充当 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;
}

最佳答案

测试竞争条件的最佳方法是在代码中添加随机 sleep 。在这种情况下,当您多次运行代码时,会增加由于竞争条件而出现错误的机会。使用随机 sleep 来确保每次运行的行为都不同。有时,阅读代码来查找此类错误的工作量太大,而测试则更容易。

关于c - 这段代码中是否存在竞争条件的可能性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21112515/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com