【发布时间】:2017-03-25 20:19:25
【问题描述】:
我写这个linux char驱动只是为了控制open call,
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/semaphore.h>
#include <linux/device.h>
#include <linux/cdev.h>
MODULE_LICENSE("GPL");
#define CLASS_NAME "myclass"
#define MINOR_NUM 0
#define MINOR_CNT 1
static struct class *myclass=NULL;
static struct device *mydevice=NULL;
static dev_t mycdevt;
static struct cdev *mycdev;
static struct semaphore *sem;
static int myopen(struct inode *inod, struct file *fp)
{
down(sem);
printk(KERN_INFO "critical section\n");
return 0;
}
static int myclose(struct inode *inod, struct file *fp )
{
up(sem);
printk(KERN_INFO "critical section freed\n");
return 0;
}
static ssize_t myread(struct file *fp, char *buf, size_t len, loff_t *off)
{
return 0;
}
static ssize_t mywrite(struct file *fp, char *buf, size_t len, loff_t *off)
{
return 0;
}
static struct file_operations fops =
{
.open = myopen,
.release = myclose,
.read = myread,
.write = mywrite,
};
static int __init myinit(void)
{
int ret;
ret = alloc_chrdev_region ( &mycdevt, MINOR_NUM, MINOR_CNT, "mycdevt");
if(ret<0)
{
printk(KERN_INFO "chardev can't be allocated\n");
// goto label;//todo
}
mycdev = cdev_alloc();//instead of cdev_alloc, we can use cdev_init(&mycdev, &fops);
if(mycdev == NULL)
{
printk(KERN_INFO"cdev_alloc failed\n");
// goto label;//todo
}
mycdev->ops = &fops;
ret = cdev_add(mycdev, mycdevt, 1);
if(ret < 0)
{
printk(KERN_INFO"cdev_add failed\n");
// goto label;//todo
}
myclass = class_create(THIS_MODULE, CLASS_NAME);
if(myclass == NULL)
{
printk(KERN_INFO"class create failed\n");
// goto label;//todo
}
mydevice = device_create(myclass, NULL, mycdevt, NULL, "mydevice");
if(mydevice == NULL)
{
printk(KERN_INFO"device create failed\n");
// goto label;//todo
}
sema_init(sem, 1);//here is the problem
printk(KERN_INFO"myinit done\n");
return 0;
}
static void __exit myexit(void)
{
device_destroy(myclass, mycdevt);
class_unregister(myclass);
class_destroy(myclass);
cdev_del(mycdev);
unregister_chrdev(MAJOR(mycdevt), "mycdevt");
printk(KERN_INFO "exited\n");
}
module_init(myinit);
module_exit(myexit);
我正在关注 ldd3 书,并尝试使用简单的 API 将信号量用于应用程序。 发生的事情是我的内核在调用 sema_init 函数时崩溃了。我读到信号量在互斥模式下使用 http://www.makelinux.net/ldd3/chp-5-sect-3
我还读到信号量不是互斥体,因为没有所有权。我还没有探索“所有权”的东西,但现在我无法制作一个简单的信号量。
我在这里做错了什么?
【问题讨论】:
-
需要注意的是,使用
struct semaphore作为互斥锁有点过时了。除非您需要支持 2.6.16 之前的旧内核,否则您可能应该使用较新的struct mutex。 -
有时人们会说,互斥量与信号量有很大不同,并且书籍说它只是一个二进制信号量。关注什么
-
有不同类型的互斥锁,包括可重入互斥锁,其中互斥锁可以由同一所有者递归锁定。内核中的
struct mutex只是一个简单的、不可重入的互斥体。 -
只看linux专业架构书。它提到了两种类型的互斥锁,一种互斥锁用作二进制信号量,称为经典互斥锁,另一种用于解决优先级反转问题。
-
那么既然重入互斥体需要记录所有者,那么当前所有者的优先级可以被操作系统提升,而更高优先级的任务正在等待互斥体?实现重入和克服优先级倒置都需要记录互斥体的当前所有者,但它们不是一回事。
标签: c linux-kernel linux-device-driver semaphore