我是一个新手试图编写一个串行驱动程序(基于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页的完整说明如下
单开设备
提供访问控制的强力方法是允许设备打开 一次只有一个过程(单一开放)。这种技术最好避免因为它 抑制用户的聪明才智。用户可能希望在同一个上运行不同的进程 设备,一个读取状态信息,另一个是写入数据。在某些情况下, 用户可以通过shell脚本运行一些简单的程序来完成很多工作 只要他们可以同时访问设备。换句话说,实现单一开放 行为相当于创建策略,这可能会阻碍你的行为 用户想要做的。仅允许单个进程打开设备具有不良属性,但它也是实现设备驱动程序的最简单的访问控制,因此在此处显示。 源代码是从名为scullsingle的设备中提取的。
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放在
device structure (Scull_Dev here)
因为从概念上讲,它属于设备。该
但是,scull驱动程序使用独立变量来保存标志,以便它可以使用相同的标记
设备结构和方法作为裸sc设备并最小化代码重复。
请告诉我任何替代方案
感谢和问候
答案 0 :(得分:3)
也许我错过了这一点,但“cotainer_of”不是一个函数,而是一个宏。如果您有移植问题,如果系统头没有实现,您可以安全地定义它。这是一个基本的实现:
#ifndef container_of
#define container_of(ptr, type, member) \
((type *) \
( ((char *)(ptr)) \
- ((char *)(&((type*)0)->member)) ))
#endif
或者这里的实现 - 更准确 - 来自最近的linux标题:
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})
答案 1 :(得分:2)
在该代码中,containerof用于轻松存储和检索正确的dev结构。在读取和写入函数内部也可以检索正确的结构,而无需访问private_data。 我不知道为什么你不想使用private-> data和containerof,但是你总是可以从struct文件指针中检索你的次要号码。
int minor=MINOR(filp->f_dentry_d_inode->i__rdev);
然后使用类似
的内容访问您的多个设备矢量struct scull_dev* dev = &scull_devices[minor]:
并使用它。
答案 2 :(得分:0)
您需要使用filp-> privatedata来存储您在读/写中也使用的“每次打开”信息。您需要确定要存储的内容以确保提供正确的信息。
可能你想要两个结构。一个“设备结构”和一个“开放结构”。开放结构可以“打开”动态分配并存储在private_data中。在发布中,它被释放。它应该有成员,以便您可以在读/写中使用它们来访问您需要的数据。
设备结构将按照“卡”进行。在你的驱动程序init中,你可能想要循环卡的数量并为每个卡创建一个新的设备结构(serial_card)。你可以使它们成为静态数组,或者动态分配,这没关系。我也会将次要号码存储在结构中。次要号码由您选择,因此从1开始并通过#cards。如果需要,可以为系统级接口保留“0”,或者从卡片的0开始。
在打开时,您将获得用户打开的次要号码。浏览您的serial_card列表以查找匹配项。如果您没有找到它,则错误打开。否则,您有自己的信息,可以使用它来分配“开放结构”,填充它,并将其存储在filp-> private_data中。
答案 3 :(得分:0)
#ifndef container_of
#define container_of(ptr, type, member) \
((type *) \
( ((char *)(ptr)) \
- ((char *)(&((type*)0)->member)) ))
#endif