linux驱动文件私有数据(字符设备基础二)

  编写linux驱动程序时,通常在驱动开发中会为设备定义相关的设备结构体,将硬件属性的描述信息全部放在该结构体中
  Linux 中并没有明确规定要使用文件私有数据,但是在 linux 驱动源码中,广泛使用了文件私有数据,这是 Linux 驱动遵循的“潜规则”,实际上也体现了Linux 面向对象的思想。structfile 结构体中专门为用户留了一个域用于定义私有数据。结构体内容如下所示:

struct file {
	union {
		struct llist_node	fu_llist;
		struct rcu_head 	fu_rcuhead;
	} f_u;
	struct path		f_path;
	struct inode		*f_inode;	/* cached value */
	const struct file_operations	*f_op;

	/*
	 * Protects f_ep_links, f_flags.
	 * Must not be taken from IRQ context.
	 */
	spinlock_t		f_lock;
	enum rw_hint		f_write_hint;
	atomic_long_t		f_count;
	unsigned int 		f_flags;
	fmode_t			f_mode;
	struct mutex		f_pos_lock;
	loff_t			f_pos;
	struct fown_struct	f_owner;
	const struct cred	*f_cred;
	struct file_ra_state	f_ra;

	u64			f_version;
#ifdef CONFIG_SECURITY
	void			*f_security;
#endif
	/* needed for tty driver, and maybe others */
	void			*private_data;

#ifdef CONFIG_EPOLL
	/* Used by fs/eventpoll.c to link all the hooks to this file */
	struct list_head	f_ep_links;
	struct list_head	f_tfile_llink;
#endif /* #ifdef CONFIG_EPOLL */
	struct address_space	*f_mapping;
	errseq_t		f_wb_err;
}

  文件私有数据的概念在 Linux 驱动中有着非常广泛的应用,文件私有数据就是将私有数据private_data 指向设备结构体。通过它可以将私有数据一路从open 函数带到read, write函数层层传入。一般是在 open 的时候赋值,read、write 时使用。open 函数中私有数据的使用如下所示

struct device_test dev1;
static int cdev_test_open(struct inode *inode,struct file *file)
{
	file->private_data=&dev1;
	return 0;
};

  在上述代码中,定义了一个设备结构体 dev1,然后在 open 函数中,将私有数据private_data指向了设备结构体 dev1。我们可以在 read write 函数中通过 private_data 访问设备结构体,如下所示:

static ssize_t cdev_test_write(struct file *file,const char _user *buf, size_t size,loff_t *off_t)
{
	struct device_test *test_dev=(struct device_test *)file->private_data;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PCI-1750是一款Advantech公司生产的32路数字I/O卡,它可以通过PCI总线连接到计算机上。在Linux系统中,可以通过编写驱动程序来控制PCI-1750卡。 以下是编写PCI-1750驱动程序的步骤: 1. 确认PCI-1750卡的硬件地址和中断号。可以使用lspci命令查看PCI设备的信息,例如: ```shell lspci -v -d 13fe: ``` 其中13fe是PCI-1750卡的厂商ID。在输出信息中可以找到PCI-1750卡的硬件地址和中断号。 2. 在驱动程序中定义PCI设备的ID信息。可以使用pci_device_id结构体来定义设备的ID信息,例如: ```c static struct pci_device_id pci1750_ids[] = { { PCI_DEVICE(0x13fe, 0x1750) }, { 0 } }; MODULE_DEVICE_TABLE(pci, pci1750_ids); ``` 其中0x13fe和0x1750分别是PCI-1750卡的厂商ID和设备ID。 3. 在驱动程序的probe函数中初始化PCI设备。可以使用pci_enable_device函数来启用PCI设备,使用pci_iomap函数来映射设备的I/O内存,例如: ```c static int pci1750_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct pci1750_private *dev; int err; dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; err = pci_enable_device(pdev); if (err) return err; dev->io_base = pci_iomap(pdev, 0, 0); if (!dev->io_base) return -EIO; /* 初始化PCI-1750卡 */ outb(0x00, dev->io_base + PCI1750_CTRL_REG); // 禁用中断 outb(0xff, dev->io_base + PCI1750_DIR_REG); // 设置为输出模式 outb(0x00, dev->io_base + PCI1750_DATA_REG); // 输出低电平 pci_set_drvdata(pdev, dev); return 0; } ``` 其中pci1750_private结构体是驱动程序的私有数据结构,io_base成员变量是设备的I/O内存地址。 4. 在驱动程序的remove函数中清理设备资源。可以使用pci_iounmap函数来解除I/O内存映射,例如: ```c static void pci1750_remove(struct pci_dev *pdev) { struct pci1750_private *dev = pci_get_drvdata(pdev); outb(0x00, dev->io_base + PCI1750_CTRL_REG); // 禁用中断 outb(0x00, dev->io_base + PCI1750_DATA_REG); // 输出低电平 pci_iounmap(pdev, dev->io_base); } ``` 5. 在驱动程序中注册字符设备。可以使用misc_register函数来注册字符设备,例如: ```c static struct miscdevice pci1750_miscdev = { .minor = MISC_DYNAMIC_MINOR, .name = "pci1750", .fops = &pci1750_fops, }; static int __init pci1750_init(void) { int err; err = misc_register(&pci1750_miscdev); if (err) return err; return pci_register_driver(&pci1750_driver); } static void __exit pci1750_exit(void) { pci_unregister_driver(&pci1750_driver); misc_deregister(&pci1750_miscdev); } module_init(pci1750_init); module_exit(pci1750_exit); ``` 其中pci1750_fops是字符设备的操作函数集。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值