阅读的心得体会

  这几天在看《》看到140页时,看到一个文件的定义:书中给出了文件的位置:/usr/src/linux/include/linux/fs.h

  关于这个头文件的位置,由于原来的linux是可以直接下载kernel源码的,因此下载下来的源码直接在目录/usr/src下面,实际上下载的文件解压后,相当于直接进入到linux目录了。

1、为了查看该文件,我下载了最新版本和次新版本,甚至还下载了一个认为比较老的版本,分别是:linux-6.6.10,linux-4.19.99,linux-3.19.9,打开文件都是不对的。

2、看了书的出版日期是2000年,那我就下载了linux-1.2.13,后来发现还是不对,作者不是个保守主义,再说搞开发的一般都比较激进些

3、下载了1999.12.29日的linux-2.3.35版本,打开后文件为:

606 struct file_operations {                                                    
 607     loff_t (*llseek) (struct file *, loff_t, int);
 608     ssize_t (*read) (struct file *, char *, size_t, loff_t *);
 609     ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
 610     int (*readdir) (struct file *, void *, filldir_t);
 611     unsigned int (*poll) (struct file *, struct poll_table_struct *);
 612     int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long     );
 613     int (*mmap) (struct file *, struct vm_area_struct *);
 614     int (*open) (struct inode *, struct file *);
 615     int (*flush) (struct file *);
 616     int (*release) (struct inode *, struct file *);
 617     int (*fsync) (struct file *, struct dentry *);
 618     int (*fasync) (int, struct file *, int);
 619     int (*check_media_change) (kdev_t dev);
 620     int (*revalidate) (kdev_t dev);
 621     int (*lock) (struct file *, int, struct file_lock *);
 622 };

这才基本接近,由于书中并没有说明是内核的具体版本,因此,只能比较接近,再来看看,2.3.51版本的

658 struct file_operations {                                                    
 659     loff_t (*llseek) (struct file *, loff_t, int);
 660     ssize_t (*read) (struct file *, char *, size_t, loff_t *);
 661     ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
 662     int (*readdir) (struct file *, void *, filldir_t);
 663     unsigned int (*poll) (struct file *, struct poll_table_struct *);
 664     int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long     );
 665     int (*mmap) (struct file *, struct vm_area_struct *);
 666     int (*open) (struct inode *, struct file *);
 667     int (*flush) (struct file *);
 668     int (*release) (struct inode *, struct file *);
 669     int (*fsync) (struct file *, struct dentry *); 
 670     int (*fasync) (int, struct file *, int);
 671     int (*lock) (struct file *, int, struct file_lock *);
 672     ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, lo     ff_t *);
 673     ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, l     off_t *);
 674 };

内容增加了两行,这就是更新的意义吧。内容就在那里,想找,努力总会找到的。

在linux下驱动开发,主要是把需要实现的功能借助内核调用实现,将不要实现的函数功能直接为NULL即可。

linux内核里的指针函数,linux-2.3.35中 /linux/arch/i386/kernel/irq.c

639 int request_irq(unsigned int irq,
640         void (*handler)(int, void *, struct pt_regs *),
641         unsigned long irqflags,
642         const char * devname,
643         void *dev_id)
644 {
645     int retval;
646     struct irqaction * action;
647 
648 #if 1
649     /*
650      * Sanity-check: shared interrupts should REALLY pass in
651      * a real dev-ID, otherwise we'll have trouble later trying
652      * to figure out which interrupt is which (messes up the
653      * interrupt freeing logic etc).
654      */
655     if (irqflags & SA_SHIRQ) {
656         if (!dev_id)
657             printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", dev    name, (&irq)[-1]);
658     }
659 #endif
660 
661     if (irq >= NR_IRQS)
662         return -EINVAL;
663     if (!handler)
664         return -EINVAL;
665 
666     action = (struct irqaction *)
667             kmalloc(sizeof(struct irqaction), GFP_KERNEL);
668     if (!action)
669         return -ENOMEM;
670 
671     action->handler = handler;
672     action->flags = irqflags;
673     action->mask = 0;
674     action->name = devname;
675     action->next = NULL;
676     action->dev_id = dev_id;
677 
678     retval = setup_irq(irq, action);
679     if (retval)
680         kfree(action);
681     return retval;
682 }                               

第640行就是指针函数的应用,应用于函数传递参数中。

再看这个文件:/linux/fs/devices.c

107 /*
108     Return the function table of a device.
109     Load the driver if needed.
110 */
111 struct file_operations * get_blkfops(unsigned int major)
112 {
113     return get_fops (major,0,MAX_BLKDEV,"block-major-%d",blkdevs);
114 }
115 
116 struct file_operations * get_chrfops(unsigned int major, unsigned int minor)
117 {
118     return get_fops (major,minor,MAX_CHRDEV,"char-major-%d",chrdevs);
119 }
120 
121 int register_chrdev(unsigned int major, const char * name, struct file_operat    ions *fops)
122 {
123     if (major == 0) {
124         for (major = MAX_CHRDEV-1; major > 0; major--) {
125             if (chrdevs[major].fops == NULL) {
126                 chrdevs[major].name = name;
127                 chrdevs[major].fops = fops;
128                 return major;
129             }
130         }
131         return -EBUSY;
132     }
133     if (major >= MAX_CHRDEV)
134         return -EINVAL;
135     if (chrdevs[major].fops && chrdevs[major].fops != fops)
136         return -EBUSY;
137     chrdevs[major].name = name;
138     chrdevs[major].fops = fops;
139     return 0;
140 }

这个函数中真正有用的似乎只有137,138行,其他都是在做各种情况测试而已。

/linux/include/linux/major.h

127 #define UNIX98_PTY_MASTER_MAJOR 128
128 #define UNIX98_PTY_MAJOR_COUNT  8
129 #define UNIX98_PTY_SLAVE_MAJOR  (UNIX98_PTY_MASTER_MAJOR+UNIX98_PTY_MAJOR_COU    NT)
130 
131 /*
132  * Tests for SCSI devices.
133  */
134 
135 #define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
136   ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
137   
138 #define SCSI_BLK_MAJOR(M) \
139   (SCSI_DISK_MAJOR(M)   \
140    || (M) == SCSI_CDROM_MAJOR)
141 
142 static __inline__ int scsi_blk_major(int m) {
143     return SCSI_BLK_MAJOR(m);
144 }
145 
146 #endif                 

此头文件最大的作用就是定义各种宏,还有带参数的宏,138~140就是一个带参数的宏,而142~144行也是一个带参数的宏,和函数已经很接近了。

posted @ 2024-01-08 09:20  叕叒双又  阅读(12)  评论(0编辑  收藏  举报