我是一个新手,正在尝试编写一个串行驱动程序(基于PCI),我不想使用container_of()
函数,因为它缺乏向下兼容性。我可能要编译模块的内核版本将是<2.6.x,所以我希望它能与大多数旧版本和新版本兼容。
我想访问串行卡驱动程序的结构成员。该结构是一个自定义结构,包含原子变量,例如use_count及其相关操作--atomic_inc(&serial_card->use_count)
。我不想使用container_of()
函数来访问它们,因为它会给我包含结构体。是否有任何替代container_of()
函数的方法?如果我没记错的话,Allesandro Roubini的《Linux设备驱动程序》在第174页|第6章:高级字符驱动程序操作中描述了一种方法。但我仍然困惑如何分配类似struct scull_dev *dev =&scull_s_device
的东西。如果结构本身包含类型为struct pc_device *dev
的变量,则上述语句会填充类似的变量,并将其分配给dev。
在我的情况下,我声明了一个结构和相关函数,如下所示:
struct serial_card
{
unsigned int id; // to identify the each card
//atomic_t use_count; // variable used to check whether the device is already opened or not
wait_queue_head_t rx_queue[64]; // queue in which the process are stored
unsigned int data_ready[64]; // queue in which the process is ready
unsigned int rx_chan; // used by interrupt handler
unsigned int base, len; // holds physical base address , holds the total area ( for each card )
unsigned int *base; // holds virtual address
/*struct cdev cdev; // kernel uses this structure to represent the EACH char device
not using the new method to represent char devices in kernel instead using the old method of register_chrdev();*/
struct pci_dev *device; // pci_dev structure for EACH device.
//struct semaphore sem; //Semaphore needed to handle the co-ordination of processes,use incase need arises
};
static struct serial_card *serial_cards; // pointer to array of structures [ depending on number of cards ],NO_OF_CARDS #defined in header file
static int serialcard_open(struct inode *inode,struct file *filep)
{
//getting the structure details of type struct serialcard,using the pointer inode->i_cdev and field type cdev
//struct serial_card *serial_cards = container_of(inode->i_cdev, struct serial_card, cdev);
// read the current value of use_count
static int Device_Open = 0;
if ( Device_Open ) //Device_Open is static varibale used here for checking the no of times a device is opened
{
printk("cPCIserial: Open attempt rejected\n");
return -EBUSY;
}
Device_Open++;
// using the card so increment use_count
//atomic_inc(&serial_cards->use_count);
//filep->private_data = serial_cards;
return 0;
}
第174-175页的完整描述如下:
单开设备
提供访问控制的暴力方法是只允许一个进程打开设备(单开)。最好避免使用这种技术,因为它会抑制用户的创造力。用户可能希望在同一设备上运行不同的进程,一个读取状态信息,而另一个则写入数据。在某些情况下,用户可以通过运行几个简单的程序来执行一些任务,只要他们能够同时访问设备。换句话说,实现单开行为相当于创建策略,这可能会妨碍用户想要做的事情。虽然只允许一个进程打开设备具有不良属性,但也是最容易为设备驱动程序实现的访问控制方式,因此在这里展示。
scullsingle设备维护了一个名为scull_s_available的atomic_t变量;该变量被初始化为1,表示该设备确实可用。open调用将减少并测试scull_s_available,如果其他人已经打开设备,则拒绝访问:
static atomic_t scull_s_available = ATOMIC_INIT(1);
static int scull_s_open(struct inode *inode, struct file *filp)
{
struct scull_dev *dev = &scull_s_device; /* device information */
if (! atomic_dec_and_test (&scull_s_available)) {
atomic_inc(&scull_s_available);
return -EBUSY; /* already open */
}
/* then, everything else is copied from the bare scull device */
if ( (filp->f_flags & O_ACCMODE) = = O_WRONLY) {
scull_trim(dev);
filp->private_data = dev;
return 0; /* success */
}
另一方面,释放调用将设备标记为不再忙碌:
static int scull_s_release(struct inode *inode, struct file *filp)
{
atomic_inc(&scull_s_available); /* release the device */
return 0;
}
通常,我们建议您将打开标志scull_s_available放置在
设备结构(此处为Scull_Dev)
中,因为从概念上讲,它属于设备。然而,scull驱动程序使用独立的变量来保存标志,以便可以使用相同的设备结构和方法作为裸scull设备并最小化代码重复。请让我知道任何此类的替代方案。
谢谢和问候。