gpt4 book ai didi

c - 带有自旋锁的定时器卡住

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:21:11 28 4
gpt4 key购买 nike

我在 Debian 6 上使用内核模块中的计时器自动编程以从 jiffies 中获取 n 个“伪随机”数字并将它们插入循环缓冲区。当第 7 次触发 fire_timer 时(当 items_cbuf == 7 时),问题就来了,当发生这种情况时,操作系统执行在以下行崩溃:

    mod_timer(&my_timer, my_timer.expires);

但之前没有,所以我不知道为什么会这样。任何提示?预期的工作方式是当缓冲区达到其容量的 80% 时,整个内容将被翻译成一个列表(即工作队列任务)

编辑:我已经放置了完整的代码,问题可能在任何地方,我不想限制分辨率。我不确定,但相关功能应该是:install_module、Open_module、Fire_timer 和 release_module。我所做的确切用途是打开并等待十秒钟,之后我从 proc 条目中读取,但由于系统卡住我无法读取

定义

#define PROC_ENTRY "modtimer"
#define PROC_ENTRY_OPS "modconfig"
#define CBUFFER_SIZE 10
#define MAX_BUFFER 512

[...]

/**********************************************************/
/*********** Open-close-read-write functions **************/
/**********************************************************/

/*Module instalation*/
int install_module(void){
int ret = 0;

/*Buffer treshold*/
TRESHOLD_SIZE = 80;
/*Delay in ticks*/
DELAY = 125;

/*timer init*/
my_timer.expires = jiffies + DELAY;
my_timer.data = 0;
my_timer.function = fire_timer;
init_timer(&my_timer);


/*workqueue init*/
workqueue_pendiente = 0;
INIT_WORK(&my_workqueue, copy_items_into_list);

/* semaphore init */
sema_init(&mtx,1);
openDevices = 0;

/*del spin_lock init*/
spin_lock_init(&spinlock);

/*buffer init*/
cbuf = create_cbuffer_t(CBUFFER_SIZE);
printk(KERN_INFO "buffer creado");
items_cbuf = 0;
/*list init*/
list_num_items = 0;

// another initializations

return ret;
}

[...]

static int modtimer_open (struct inode *inod, struct file *f){
int ret = 0;

//Iniciar el timer
if(openDevices==0){
my_timer.expires = jiffies + DELAY;
add_timer(&my_timer);
}

try_module_get(THIS_MODULE);
openDevices++;

return ret;
}

static int modtimer_release (struct inode *inod, struct file *f){

del_timer_sync(&my_timer);
flush_scheduled_work();

remove_cbuffer_t (cbuf); //delete the buffer
vacia_list_item(); //removes every element from the list

openDevices--;
module_put(THIS_MODULE);

return 0;
}

static ssize_t modtimer_read (struct file *file, char *user, size_t nbits, loff_t * offset){
struct list_head* pos = mylist.next;
struct list_head* auxpos;
list_item_t* item;
char aux[MAX_BUFFER];
char aux2[10];
int total =0;
int subt =0;
int hecho = 0;


if(down_interruptible(&mtx)){
return -EINTR;
}

while (hecho == 0){
if(pos == pos->next || list_num_items ==0){
hecho++;
}else{
item = list_entry(pos, list_item_t, links);
subt=sprintf(aux2, "%d\n",item->data);
auxpos = pos->next;
if(subt + total > MAX_BUFFER ) {
hecho++;

}else {

total+= sprintf(&aux[total],"%i\n",item->data);
list_del(pos);
vfree(item);
list_num_items--;
}
subt = 0;
pos = auxpos;
}
}

aux[total] = '\0';
up(&mtx);

copy_to_user(user,aux,total);

return total;
}

/*********************************************************/
/****************** Planified functions ******************/
/*********************************************************/

//Fills a buffer with integgers and planifies when is about to be out of space
void fire_timer(unsigned long data){
unsigned long flags;
int rnd = jiffies & 0xFF;

spin_lock_irqsave(&spinlock,flags);
if(!is_full_cbuffer_t(cbuf))
{
items_cbuf++;
insert_cbuffer_t(cbuf, rnd);
}


printk(KERN_INFO "workqueue_pendiente = %d, items_cbuf=%d, CBUFFER_SIZE = %d, TRESHOLD_SIZE = %d, umbral = %d",
workqueue_pendiente, items_cbuf, CBUFFER_SIZE, TRESHOLD_SIZE, (CBUFFER_SIZE*TRESHOLD_SIZE)/100);

if(workqueue_pendiente == 0 &&
items_cbuf >= (CBUFFER_SIZE*TRESHOLD_SIZE)/100 )
{
workqueue_pendiente=1;

schedule_work(&my_workqueue);
}

my_timer.expires = jiffies + DELAY;
spin_unlock_irqrestore(&spinlock,flags);
mod_timer(&my_timer, my_timer.expires);
}

void copy_items_into_list(struct work_struct *work){ //Dumps the buffer into the list
unsigned long flags;
list_item_t *items[items_cbuf];
int numbers[items_cbuf];
int a = -1;

while (++a < items_cbuf){
items[a] = vmalloc(sizeof(list_item_t));
}
a = -1;

spin_lock_irqsave(&spinlock,flags);
while(++a < items_cbuf){
numbers[a] = *head_cbuffer_t(cbuf);
remove_cbuffer_t(cbuf);
}
workqueue_pendiente = 0;
spin_unlock_irqrestore(&spinlock,flags);

a = -1;
if (down_interruptible(&mtx)) /*BLOQUEO*/
return;


while (++a < items_cbuf){//size_cbuffer_t(cbuf) > 0){
items[a]->data = numbers[a];
list_add_tail(&items[a]->links, &mylist);
list_num_items++;
}


up(&mtx);
}

这是我在系统卡住之前可以获得的代码:

Kernel Error

"sleeping, remaining 6"是我测试程序的消息,内容就是

int main(void){
int l;
int i=11;
char bla[512];
l = open("/proc/modtimer",O_RDONLY);
bla[2] = '\0';
while(--i>=0){
printf("sleeping, remaining %d\n",i);
sleep(1);
}
read(l,bla,128);
close(l);
printf("numbers:%s",bla);
}

最佳答案

fire_timer() 中,您调用了 spin_unlock_irqrestore(&spinlock,flags); 两次,而只调用了一次 spin_lock_irqsave()

关于c - 带有自旋锁的定时器卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21440265/

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