920 likes | 1.17k Views
Linux I/O. 9762599 劉哲維 9762579 郭逸旻. OUTLINE. I/O Architecture The Device Driver Model Device Files Device Drivers Character Device Drivers. I/O Architecture. PC Architecture. I/O Architecture. I/O Bus I/O Port I/O Interface I/O Controller. I/O Ports.
E N D
Linux I/O • 9762599 劉哲維 • 9762579 郭逸旻
OUTLINE • I/O Architecture • The Device Driver Model • Device Files • Device Drivers • Character Device Drivers
I/O Architecture • I/O Bus • I/O Port • I/O Interface • I/O Controller
I/O Ports • Each device connected to the I/O bus has its own set of I/O addresses, which are usually called I/O ports. • Four special assembly language instructions • In() • Ins() • Out() • Outs()
I/O Ports • Kernel treats I/O ports as "resources“ • Tree-like data structure
I/O Ports • Device driver use the following functions: root (0~65535) A (0~3) B (16~19) C (20~23) New (4~7)
request_resource() <kernel/resource.c> static struct resource * __request_resource(struct resource *root, struct resource *new) { resource_size_t start = new->start; resource_size_t end = new->end; struct resource *tmp, **p; if (end < start) return root; if (start < root->start) return root; if (end > root->end) return root; p = &root->child; for (;;) { tmp = *p; if (!tmp || tmp->start > end) { new->sibling = tmp; *p = new; new->parent = root; return NULL; } p = &tmp->sibling; if (tmp->end < start) continue; return tmp; }}
release_resource() static int __release_resource(struct resource *old) { struct resource *tmp, **p; p = &old->parent->child; /*指向第一個child*/ for (;;) { tmp = *p; if (!tmp) break; if (tmp == old) { *p = tmp->sibling; old->parent = NULL; return 0; } p = &tmp->sibling; } return -EINVAL; }
I/OInterfaces • Between I/O port and Device Controller • Acts as an interpreter that translates for the I/O ports and the device • Connect through an IRQ line to a Programmable Interrupt Controller
I/OInterfaces • Custom I/O interfaces • Graphic interface • Disk interface • Network interface • General-purpose I/O interfaces • Parallel port • Serial port • USB • PCMCIA
Device Controllers • CPU to I/O • Interprets the high-level commands received from the I/O interface and forces the device to execute specific actions • I/O to CPU • Interprets the electrical signals received from the device and modifies (through the I/O interface) the value of the status register • Disk Controller
Sysfs File system The sysfs filesystem is a special virtual filesystem that is usually mounted on the /sys directory. It allows User Mode applications to access kernel internal data structures of device driver model.
kobjects • The core data structure of the device driver model • Usually embedded inside a “Container” that describe the device、driver、bus. • Each kobject corresponds to a directory in sysfsfilesystem
kobjects Embedding a kobject inside a container allows the kernel to: Keep a reference counter for the container Maintain hierarchical lists or sets of containers (for instance, a sysfs directory associated with a block device includes a different subdirectory for each disk partition) Provide a User Mode view for the attributes of the container
kobjects kref:Reference counter Ktype: Release method Sysfs_ops Default attribute
ktype In Document/kobject.txt
kset “kset” is a collection of kobjects of the same ktype
kset An embedded kobject: Kobject_get() instead of kset_get() Kset data structure can be embedded in a container Kset data structure can be a member of another kset
subsystem A collection of ksets kset An embedded kset Can also be embedded in a container Rwsem A read-write semaphore
Device <include/linux/device.h>
Driver <include/linux/device.h>
In drivers/block/~ In drivers/char/~
Bus <include/linux/device.h>
Registration Add into the internal kernel data structure register kobject_register( ) kset_register ( ) device_register( ) driver_register( ) unregister
Device File • I/O devices are treated as special files • Device file in : /dev directory, like /dev/hda • Twotypes of device files: • Block device • Fixed transmission • Storage device • Character device • Byte-transmission • At least 4 system call • Network interface
Device File • i-node of device file: • Must include an identifier of the hardware device • Type of device file:Block or Character • Major number • Minor number • mknod() system call: • Used to create device file • It needs name, type , major and minor number • mknod /dev/usbservice b 8 0
Device File Handling • 8-bit major and minor number are insufficient for large-scale system • 12-bit major and 20-bit minorin 32-bit dev_t • MAJOR、MINOR、MKDEV Macro • major=MAJOR(inode->i_rdev) • minor=MINOR(inode->i_rdev) • Compatible with old device file • Dynamicallyallocate device number and create device file
Dynamicallycreate device file • At the system startup the /dev directory is emptied • Device files can be created "on demand" • udev program scans the subdirectories of /sys/class looking for the dev files
Levels of Kernel Support • No support at all • The application program interacts directly with the device's I/O ports • Minimal support • The kernel does not recognize the hardware device, but does recognize its I/O interface. • kernel takes care of the I/O interface by offering a device file • the application program handles the external hardware device by reading and writing the device file • Extended support • The kernel recognizes the hardware device and handles the I/O interface itself.
Device Driver • Device Driver • A device driver is the set of kernel routines that makes a hardware device respond to the programming interface defined by the canonical set of VFS functions (open, read, lseek, ioctl, and so forth) that control a device.
Device Driver Registering • Device Driver Registering • Allocating a new device_driver descriptor • Insert it in the data structures of the device driver model • Link it to the corresponding device file(s) • System call on device file • translated by the kernel into an invocation of a suitable function of a corresponding device driver
Device Driver Registering • character device • register_chrdev() • ex: /drivers/char/Lp.c • block device • register_blkdev() • ex: /drivers/block/hd.c
Device Driver Registering • /include/linux/fs.h externint register_chrdev(unsigned int,const char *,conststruct file_operations *); • /drivers/chr/lp.c if (register_chrdev (LP_MAJOR, "lp", &lp_fops)) { printk (KERN_ERR "lp: unable to get major %d\n", LP_MAJOR); return -EIO;//I/O發生錯誤 }
Device Driver Registering • /drivers/chr/lp.c static const struct file_operations lp_fops = { .owner = THIS_MODULE, .write = lp_write, .ioctl = lp_ioctl, .open = lp_open, .release = lp_release, #ifdef CONFIG_PARPORT_1284 .read = lp_read, #endif };
Device Driver Registering • struct module *owner; • 不同於file_operations結構裡的其它欄位,此欄位不是函式指標,而是一個指向結構所屬模組的指標。驅動程式本身用不到此欄位,因為他是供核心用來維護模組的用量計次(usage count)。 • ssize_t (*read) (struct file *,char *,size_t,loff_t *); • 用於擷取出裝置上的資料。若將此欄位設定為NULL,則read()系統呼叫發生-EINVAL失敗。(Invalid argument,引數值無效) ,如果成功,則傳回一個非負數值,代表成功讀取的位元數。 • ssize_t (*write) (struct file *, const char *, size_t, loff_t *); • 將資料寫入裝置。若發生錯誤,則觸發write()系統呼叫的行程會收到-EINVAL。如果成功,write將傳回一個非負值,代表成功寫出的位元數。
Device Driver Registering • int (*ioctl) (struct inode *, struct file *, unsigned int,unsigned long); • 每個裝置或多或少都有其特殊功能,標準的作業方法不見得能提供應用程式所需要的一切功能(ex:格式化),對於隨裝置而定的功能,應用程式可透過ioctl()系統呼叫來執行一系列裝置特有命令,而ioctl作業發法的任務,就是實現在類特殊命令。 • int (*open) (struct inode *, struct file *); • 開啟,這必定是裝置檔操作程序的第一步,但是驅動程式並非一定要宣告一個對應方法不可。如果將此欄位指向NULL,開啟裝置的動作一定會成功,只不過驅動程式不會收到通知而已。 • int (*release) (struct inode *, struct file *); • 在file結構被釋放之前,此方法會被呼叫。(並非,每次呼叫close( )都會觸發release)
Device Driver Registering • /fs/char_dev.c static struct char_device_struct { struct char_device_struct *next;//The pointer to next element in hash collision list unsigned int major; unsignedint baseminor;//minor number int minorct; //The interval size char name[64]; struct cdev *cdev;//pointer to the character device driver descriptor } *chrdevs[CHRDEV_MAJOR_HASH_SIZE];
Device Driver Registering • Major number • 代表裝置所配合的驅動程式 • 當核心收到open()系統呼叫時,就是依據“major number”來選擇驅動程式 • Minor number • 驅動程式以次編號來辨認同類裝置的個體 • 核心本身用不到,只有驅動程式自己才知道次編號的意義 • 每當核心要呼叫驅動程式,都必須讓驅動程式知道,他應該作用在哪一個裝置上;驅動程式以裝置編號來變任期作用對象。(裝置編號=major number + minor number) Major (12 bits) Minor(20 bits)
Device Driver Registering • /include/linux/Cdev.h struct cdev { struct kobject kobj; //Embedded kobject struct module *owner; conststruct file_operations *ops; struct list_head list;// Head of the list of inodes relative to device files for this character device dev_t dev; //major and minor number unsignedint count; //size of the range of device number };
Device Driver Registering kobj file_operations