关于linux的filp->private_data解释

首先给出filp的结构体:struct file

struct file {

  union {

        struct list_head fu_list; //文件对象链表指针linux/include/linux/list.h

        struct rcu_head fu_rcuhead; //RCU(Read-Copy Update)是Linux 2.6内核中新的锁机制

   } f_u;

  struct path f_path; //包含dentry和mnt两个成员,用于确定文件路径

  #define f_dentry f_path.dentry //f_path的成员之一,当前文件的dentry结构

  #define f_vfsmnt f_path.mnt //表示当前文件所在文件系统的挂载根目录

  const struct file_operations *f_op; //与该文件相关联的操作函数

  atomic_t f_count; //文件的引用计数(有多少进程打开该文件)

  unsigned int f_flags; //对应于open时指定的flag

  mode_t f_mode; //读写模式:open的mod_t mode参数

       loff_t     f_pos;//当前文件指针位置

  off_t f_pos; //该文件在当前进程中的文件偏移量

  struct fown_struct f_owner; //该结构的作用是通过信号进行I/O时间通知的数据。

  unsigned int f_uid, f_gid;// 文件所有者id,所有者组id

  struct file_ra_state f_ra; //在linux/include/linux/fs.h中定义,文件预读相关

  unsigned long 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;

      spinlock_t f_ep_lock;

  #endif /* #ifdef CONFIG_EPOLL */

  struct address_space *f_mapping;

  };

找到private成员(前后已用空白行隔开),显然该成员是void*类型,也就是说我们可以将任意的地址赋给该指针变量

在Linux驱动字符设备开发中:

首先:

struct file *filp

定义结构体:

struct cdev 
{
struct kobject kobj;
struct module *owner;
const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};

继续定义结构

struct test_dev{
dev_t devid; /* 设备号 */
struct cdev cdev; /* cdev */
struct class *class; /* 类 */
struct device *device; /* 设备 */
int major; /* 主设备号 */
int minor; /* 次设备号 */
};

再定义:

struct test_dev testdev;

此时:在test_open()应用函数里取指:&testdev并赋值给filp->private_data即    

static int test_open(struct inode *inode, struct file *filp)
{
filp->private_data = &testdev; /* 设置私有数据 */
return 0;
}

也就是说此时的filp->private为一个指向结构体test_dev的指针

此时将:

struct   test_dev *dev = filp->private_data;

此时也就是说dev存放的就是该私有数据的结构体指针了

通过dev就可以直接访问该私有test的私有数据了。

 

  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
下面是一个简单的Linux UART驱动程序的框架: ```c #include <linux/init.h> #include <linux/module.h> #include <linux/device.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/uaccess.h> #include <linux/serial.h> #define DRIVER_NAME "my_uart" // 定义字符设备结构体 struct my_uart_dev { struct cdev cdev; struct class *class; struct device *device; dev_t devno; struct uart_port uart; }; static int my_uart_open(struct inode *inode, struct file *filp) { struct my_uart_dev *dev = container_of(inode->i_cdev, struct my_uart_dev, cdev); filp->private_data = dev; // 初始化串口 uart_config(&dev->uart); return 0; } static ssize_t my_uart_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct my_uart_dev *dev = filp->private_data; ssize_t ret; // 从串口读取数据到buf中 ret = uart_read(&dev->uart, buf, count); return ret; } static ssize_t my_uart_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { struct my_uart_dev *dev = filp->private_data; ssize_t ret; // 将buf中的数据写入到串口中 ret = uart_write(&dev->uart, buf, count); return ret; } static const struct file_operations my_uart_fops = { .owner = THIS_MODULE, .open = my_uart_open, .read = my_uart_read, .write = my_uart_write, }; static int __init my_uart_init(void) { int ret; struct my_uart_dev *dev; // 分配设备结构体的内存 dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { ret = -ENOMEM; goto err_alloc_dev; } // 初始化串口 uart_init_port(&dev->uart); // 注册字符设备 dev->devno = MKDEV(0, 0); ret = alloc_chrdev_region(&dev->devno, 0, 1, DRIVER_NAME); if (ret < 0) { goto err_alloc_chrdev_region; } cdev_init(&dev->cdev, &my_uart_fops); dev->cdev.owner = THIS_MODULE; ret = cdev_add(&dev->cdev, dev->devno, 1); if (ret < 0) { goto err_cdev_add; } // 创建设备节点 dev->class = class_create(THIS_MODULE, DRIVER_NAME); if (IS_ERR(dev->class)) { ret = PTR_ERR(dev->class); goto err_class_create; } dev->device = device_create(dev->class, NULL, dev->devno, NULL, DRIVER_NAME); if (IS_ERR(dev->device)) { ret = PTR_ERR(dev->device); goto err_device_create; } return 0; err_device_create: class_destroy(dev->class); err_class_create: cdev_del(&dev->cdev); err_cdev_add: unregister_chrdev_region(dev->devno, 1); err_alloc_chrdev_region: kfree(dev); err_alloc_dev: return ret; } static void __exit my_uart_exit(void) { struct my_uart_dev *dev = container_of(&my_uart_fops, struct my_uart_dev, cdev); // 删除设备节点 device_destroy(dev->class, dev->devno); class_destroy(dev->class); // 注销字符设备 cdev_del(&dev->cdev); unregister_chrdev_region(dev->devno, 1); // 释放设备结构体的内存 kfree(dev); } module_init(my_uart_init); module_exit(my_uart_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your name"); MODULE_DESCRIPTION("My UART driver"); ``` 需要注意的地方: 1. 在字符设备结构体`my_uart_dev`中,有一个`struct uart_port uart`成员,用来保存串口的状态。 2. 在驱动初始化函数`my_uart_init`中,需要分配`my_uart_dev`结构体的内存,并初始化`struct uart_port uart`成员。 3. 在驱动初始化函数`my_uart_init`中,需要注册字符设备,并创建设备节点。 4. 在驱动退出函数`my_uart_exit`中,需要删除设备节点,并注销字符设备。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小灰俠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值