首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >替代container_of()

替代container_of()
EN

Stack Overflow用户
提问于 2011-03-29 07:32:34
回答 4查看 2.9K关注 0票数 3

我是一个新手,试图编写一个串行驱动程序(基于PCI),我不想使用container_of(),因为缺少向下的compatibility.The内核版本,我可能会编译模块< 2.6.x,所以我想使它与大多数新旧版本兼容。

我想访问串行卡driver.the结构的结构成员是一个自定义的结构成员,例如包含原子变量-- use_count及其相关操作-- atomic_inc(&serial_card->use_count).I不想使用container_of()函数来访问它们,这将给我包含的结构-- container_of() function.If有什么可替代的地方,我没有错。Allesandro描述的文本LINux设备驱动程序在第6章174号页上描述了一种方法:高级Char驱动程序操作。但是我仍然对如何分配像struct scull_dev *dev = &scull_s_device这样的东西很感兴趣。如果结构本身包含一个类型为struct pc_device *dev的变量,则上面的语句填充一个类似的变量,并分配给dev,

在我的例子中,我声明了一个结构和相关功能,如下所示

代码语言:javascript
复制
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的scull_s_available变量;该变量被初始化为值为1,表明该设备确实可用。打开的调用减少并测试scull_s_available,如果其他人已经打开设备,则拒绝访问:

代码语言:javascript
复制
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 */
  }

另一方面,释放调用标志着设备不再繁忙:

代码语言:javascript
复制
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驱动程序使用独立的变量来保存标志,这样它就可以使用与裸scull设备相同的设备结构和方法,并尽量减少代码重复。

请告诉我有什么别的办法吗?

谢谢和问候

EN

回答 4

Stack Overflow用户

发布于 2011-03-29 12:35:44

也许我错过了重点,但是"cotainer_of“不是一个函数,而是一个宏。如果您有移植方面的问题,如果系统标头没有实现,您可以通过自己的服务器安全地定义它。这里是一个基本的实现:

代码语言:javascript
复制
#ifndef container_of
#define container_of(ptr, type, member) \
 ((type *)                              \
   (  ((char *)(ptr))                   \
    - ((char *)(&((type*)0)->member)) ))

#endif

或者,下面是最近linux头中的实现--更准确地说:

代码语言:javascript
复制
#define container_of(ptr, type, member) ({ \
                const typeof( ((type *)0)->member ) *__mptr = (ptr); 
                (type *)( (char *)__mptr - offsetof(type,member) );})
票数 4
EN

Stack Overflow用户

发布于 2011-12-16 12:08:29

在该代码中,容器用于轻松地存储和检索正确的dev结构。在读和写函数中也可以检索到正确的结构,而无需访问private_data。我不知道您为什么不想使用私有->数据和容器,但是您总是可以从struct文件指针中检索您的次要数字。

代码语言:javascript
复制
int minor=MINOR(filp->f_dentry_d_inode->i__rdev);

然后使用以下内容访问多个设备向量

代码语言:javascript
复制
struct scull_dev* dev = &scull_devices[minor]:

并利用它。

票数 2
EN

Stack Overflow用户

发布于 2011-04-16 13:12:07

您需要使用filp->私有数据来存储在读/写中也使用的“每次打开”信息。您需要决定存储什么,以确保正确的信息是可用的。

也许你想要两种结构。一个“设备结构”和一个“开放结构”。开放结构可以在“开放”中动态分配,并存储在private_data中。在释放的时候,它会被释放。它应该有成员,这样您就可以在读/写中使用它们来访问所需的数据。

设备结构将按“卡”排列。在您的驱动程序init中,您可能希望循环卡片的数量,并为每个卡创建一个新的设备结构(serial_card)。您可以让它们成为一个静态数组,或者动态分配,这并不重要。我也会把小数字存储在结构里。小数是由你选择的,所以从1开始,再通过#卡片。如果需要,可以为系统级接口保留"0“,也可以只从0开始。

在open中,您将得到用户打开的次要号码。检查您的serial_card列表,寻找匹配。如果你找不到它,错误就会被打开。否则,您就有了您的信息,可以使用它分配一个“开放结构”,填充它,并将其存储在filp->private_data中。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5469255

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档