770 likes | 1.12k Views
Linux I/O. 葉再傳 吳致穎 丁俊宏. Outline. I/O Architecture The Device Driver Model Device Files Device Drivers Character Device Drivers. Outline. I/O Architecture The Device Driver Model Device Files Device Drivers Character Device Drivers. PC Architecture. Computer uses bus to
E N D
Linux I/O 葉再傳 吳致穎 丁俊宏
Outline • I/O Architecture • The Device Driver Model • Device Files • Device Drivers • Character Device Drivers
Outline • I/O Architecture • The Device Driver Model • Device Files • Device Drivers • Character Device Drivers
PC Architecture • Computer uses bus to connect CPU(s), RAM and score of I/O devices together. • There are several types of buses linked together by bridges.
I/O Architecture • The data path that connects a CPU to an I/O device is generically called an I/O bus. • The I/O bus is connected to each I/O device by means of a hierarchy of hardware components including up to three elements: • I/O ports • I/O interfaces • I/O(device) controllers.
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 allow the CPU to read from and write into an I/O port. • in: Read data from an I/O port. • ins: Read sequences of data from an I/O port. • out: Write data to an I/O port. • outs: Write sequences of data to an I/O port.
I/O Interface • Since writing into I/O ports must follow the specification of bus, the signal that send to the devices must translate into the information that the devices can understand. • An I/O interface is a hardware circuit inserted between a group of I/O ports and the corresponding device controller. • It acts as an interpreter that translates the values in the I/O ports into commands and data for the device.
Two Types of Interface • Custom I/O interfaces • Keyboard interface • Disk interface • Network interface • General-purpose I/O interfaces • Parallel port • Serial port • USB
I/O Controllers • A complex device (like disk) may require a device controller to drive it. • It translate the signal between high-level commands and low level electrical signals.
An Example (Write Disk) CPU Time i: out(x) Time i+1: out(y) … … … Software I/O Port Hardware I/O Interface Write this block of data Position the disk head on the right track Write the data inside the track I/O Controller
I/O Ports Management • While accessing I/O ports is simple, detecting which I/O ports have been assigned to I/O devices may not be easy. • Often a device driver must blindly write into some I/O port to probe the hardware device. • If this I/O port is already used by some other hardware device, a system crash could occur. • To prevent such situations, the kernel keeps track of I/O ports assigned to each hardware device by means of resources.
Resource • A resource represents a range of I/O port addresses • Tree-like data structure • <include/linux/ioport.h>
Request and release resource • <kernel/resource.c> 2 5 7 10 0 root (0~10) Dev A (2~5) new (5~7)
Outline • I/O Architecture • The Device Driver Model • Device Files • Device Drivers • Character Device Drivers
Device Management • I/O architecture is big system including buses, devices, and device drivers. • Linux uses a model called device driver model to simulate and manage the whole system • The model provides several benefits such as: • The capability to enumerate all the devices in the system • The capability to link devices to their drivers and vice versa • The ability to power down devices in the correct order • Minimization of code duplication
What’s Device Driver Model? • Internal kernel data structure • It means that processes in user mode can’t access it. • Tree-like structure
The sysfs Filesystem • 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.
Components of Device Driver Model • There are mappings between /sysfs and kernel data structure.
Device • <include/linux/device.h>
Driver • <include/linux/device.h>
Bus • <include/linux/device.h>
Kobject • <include/linux/kobject.h> • The core data structure of the device driver model. • Embedded inside larger objects.
Kset • <include/linux/kobject.h> • A collection of kobjects of the same type
Related Function • Add into the internal kernel data structure • register • kobject_register( ) • kset_register ( ) • device_register( ) • driver_register( ) • unregister • kobject_unregister • kset_unregister( ) • device_unregister( ) • driver_unregister( )
Outline • I/O Architecture • The Device Driver Model • Device Files • Device Drivers • Character Device Drivers
Device file Introduction(1) • I/O devices are treated as special files vim helloworld.c write() Device File /dev / lp0(印表機 ) Standard File /home / helloworld.c Device File VFS write() Device driver need to define how to write Write to printer buffer to print Write Hdisk blocks
Device file Introduction(2) • Device file in : /dev directory • Device files can be of two type • Block • 固定區塊傳輸 • Random Access • EX: Hard Disk , DVD • Character • 傳輸單一字元 • Continuous data behavior • EX:音效卡 鍵盤… • Another types • Network( do not presented by Device File ) • Combine Character & Block • Ex: FTP
Device file Introduction(3) • Three different kinds of device files • old-style device files(還是最常用) • /dev • devfs (Device File System) device files • Included in Linux 2.3.46 • Do not Default compile in 2.6.7~2.6.18 --CONFIG_DEVFS_FS=Y • udev • Included in Linux 2.6.13~
Old-style device files(1) • A real file stored in a file-system • Store Major three Information… • (1)Kind of device file • Character of Block • Two main attributes • (2)Major number • Identify the device type (1~254) • Main kinds of device driver Ex: /dev/hda , /dev/fd0 • (3)Minor number • Sub. (Logic) device. Sub of Major Ex:/dev/hda2 • Merged in a 16-bit dev_t number • mknod() system call • Create old-style device files • fs/namei.c
Old-style device files(2) • /Documents/devices.txt • http://www.lanana.org/docs/device-list/ • 16bits==65536 Both Char. and Block can use at most 65536 devices. Same Major , Diff. Type Same Major , Diff. Minor Exception: Do not mapping to real HW
mknod() system call (1) (2.6.25) Command: mknod device-namedevice-typemajor-numberminor-number EX: mknod /dev/ttyS0c464 In /fs/Namei.c asmlinkage long sys_mknod(const char __user *filename, int mode, unsigned dev) { return sys_mknodat( AT_FDCWD, filename, mode, dev); } dev_t -100 :represent use current working-dir Include\linux\State.h We interest BLK & CHR Include/linux/Types.h typedef __u32 __kernel_dev_t; typedef __kernel_dev_t dev_t;
mknod() system call (2) (2.6.25) In /fs/Namei.c asmlinkage long sys_mknodat(int dfd , const char __user *filename , int mode , unsigned dev) { …… if (!IS_ERR(dentry)) { switch (mode & S_IFMT) { case 0: case S_IFREG: error = vfs_create (nd.path.dentry->d_inode,dentry,mode,&nd); break; case S_IFCHR: case S_IFBLK: error = vfs_mknod (nd.path.dentry->d_inode , dentry ,mode, new_decode_dev(dev) ); break; case S_IFIFO: case S_IFSOCK: error = vfs_mknod (nd.path.dentry->d_inode,dentry,mode,0); break; case S_IFDIR: error = -EPERM; break; default: error = -EINVAL; } dput(dentry); } ……. return error; } Directory entry • S_ISCHR (mode) State.h • == ((mode & S_IFMT)==S_IFCHR ) • Return non-zero if the mode is from a character special device file. • S_ISBLK (mode) • == ((mode & S_IFMT)==S_IFBLK ) • Return non-zero if the mode is from a block special device file.
mknod() system call (3) (2.6.25) In /fs/Namei.c int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) { int error = may_create(dir, dentry, NULL); if (error) return error; if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD)) return -EPERM; //EPERM 1 /* Operation not permitted */ if (!dir->i_op || !dir->i_op->mknod) return -EPERM; error = security_inode_mknod(dir, dentry, mode, dev); if (error) return error; DQUOT_INIT(dir); error = dir->i_op->mknod(dir, dentry, mode, dev); if (!error) fsnotify_create(dir, dentry); return error; } /include/linux/Security.h security_operations Include/linux/Fs.h struct inode_operations
mknod() system call (4) (2.6.25) error = dir->i_op->mknod( dir, dentry, mode, dev); Include/linux/Fs.h struct inode_operations { …… int (*mknod) (struct inode *,struct dentry *,int,dev_t); …… } How to inplement inode _opera -tion about mknod?? Example : Ext3 file system In /fs/Namei.c const struct inode_operations ext3_dir_inode_operations = { …… .mknod = ext3_mknod, …… }; Ans…
mknod() system call (5) (2.6.25) error = dir->i_op->mknod( dir, dentry, mode, dev); Example : Ext3 file system In /fs/Namei.c static int ext3_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) { struct inode *inode; ……… inode = ext3_new_inode (handle, dir, mode); err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, inode->i_mode, rdev); #ifdef CONFIG_EXT3_FS_XATTR inode->i_op = &ext3_special_inode_operations; #endif ……… return err; }
mknod() system call (6) (2.6.25) Example : Ext3 file system In /fs/Inode.c void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev) { inode->i_mode = mode; if (S_ISCHR(mode)) { inode->i_fop = &def_chr_fops; inode->i_rdev = rdev; } else if (S_ISBLK(mode)) { inode->i_fop = &def_blk_fops; inode->i_rdev = rdev; } else if (S_ISFIFO(mode)) inode->i_fop = &def_fifo_fops; else if (S_ISSOCK(mode)) inode->i_fop = &bad_sock_fops; else printk(KERN_DEBUG "init_special_inode : bogus i_mode (%o)\n", mode); } const struct file_operations def_blk_fops = { .open = blkdev_open, .release = blkdev_close, .llseek = block_llseek, .read = do_sync_read, .write = do_sync_write, .aio_read = generic_file_aio_read, ……… More }; 順便說明~vfs怎找到device對應的執行動作
Old-style device files(3) • Major & Minor have two major problems • 8-bit long numbers limiting factor for several hardware devices. • HLA , Super Computing… • Sol: In Linux 2.6 , 12 bits major + 20bits minor in 32bits dev_t • 與舊16bits 向下相容 • Ex: Major 257 block SSFDC Flash Translation Layer • Most of the devices don’t exist(所以files 在 /dev下大部分都沒對應到真正的設備). • Increases the time taken to look up an inode. • Sol:Dynamic allocate device file
devfs (Device File System) (1) • Devfs is virtual filesystem • A registered device file automatically appears in a devfs virtual directory. • Different to old-style device files • 這種device file的inode object只有在此file被access時才產生,而不是註冊時產生 /devfs /dev Ex: ide/host0/ ide/host1/ 自己建立起 Dev. namespace
devfs (Device File System) (2) • Advantage: allows drivers to register devices by name rather than bymajorand minor numbers. ex: ide0 可以是/dev/hda 亦可以使用註冊成/devfs/disc/disc0 • I/O drivers register devices by invoking devfs_register() • Documents/filesystems/devfs/README • include/linux/devfs_fs_kernel.h ***兩者可以共存***
udev (user space device)(1) • The successor of devfs and hotplug, which means that it handles the /dev directory and all user space actions when adding/removing devices, including firmware load. ---WiKi • Feature • dynamic replacement for /dev • 傳統 devfs不能夠動態分配major and minor,udev能夠動態分配(類似Internet DHCP) • 動態產生 hotplug event • device naming • 類似網路DNS作法。能夠給予裝置有意義名稱供 • API to access info about current system devices • 提供了一组易用的API去操作sysfs,code reuse In 2.6, sysfs creates -- sysfs的任務是export system struct to user process space
Outline • I/O Architecture • The Device Driver Model • Device Files • Device Drivers • Character Device Drivers
Levels of Kernel Support No support at all(完全沒輔助) • 要靠application program自己處理跟I/O port之間的互動 • EX: 傳說中的 Assembler hand-coding 達人 Minimal support • Kernel只認得I/O的interface,不認得這是什麼device. • Kernel會提供一個device file, application program就對這file做access來操縱device. • Only serial port and parallel port can be handled with this approach. • EX: Embedded實驗: 寫 RS232 程式連結GSM模組 Extended support • Kernel 認得這個device並且親自處理與device之間的互動. • Any general-purpose I/O interface except the serial and the parallel ports.(ex:USB, PCMCIA, SCSI)
Device Driver Registering & Initialing(1) • Device driver • A device driver is a software layer that makes a hardware device respond to a well-defined programming interface. • Device Driver Registering • System call on device file → function of device driver (by kernel) • Register a device driver • Link it to the corresponding device file • 呼叫register_chrdev(), register_blkdev()是分別對character device和block device做註冊動作. Example: /drivers/char/Lp.c if (register_chrdev (LP_MAJOR, "lp", &lp_fops)) char_device_struct block_device_struct
Device Driver Registering & Initialing(2) /drivers/char/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 }; Example: /drivers/char/Lp.c if (register_chrdev (LP_MAJOR, "lp", &lp_fops)) dev_num dev_name /fs/Char_dev.c static struct char_device_struct { struct char_device_struct *next; unsigned int major; unsigned int baseminor; int minorct; char name[64]; struct file_operations *fops; struct cdev *cdev; } *chrdevs[CHRDEV_MAJOR_HASH_SIZE]; //255 /include/linux/Cdev.h struct cdev { struct kobject kobj; struct module *owner; const struct file_operations *ops; struct list_head list; dev_t dev; unsigned int count; };
Device Driver Registering & Initialing(3) 最重要 device operation 資料存在cdev 1 2 /fs/Char_dev.c int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops) { struct char_device_struct *cd; struct cdev *cdev; char *s; int err = -ENOMEM; cd = __register_chrdev_region (major, 0, 256, name); if (IS_ERR(cd)) return PTR_ERR(cd); cdev = cdev_alloc(); if (!cdev) /*error handle */ cdev->owner = fops->owner; cdev->ops = fops; /*setting cdev kobject name*/ err = cdev_add(cdev, MKDEV(cd->major, 0), 256); /*if err goto errhandle */ cd->cdev = cdev; return major ? 0 : cd->major; /*error handler*/ }
Device Driver Registering & Initialing(4) • Driver Registering & Initialing • 將system resources分配給這個device driver. • Make sure the resources are obtained when needed • Use counter • 初始device driver時,呼叫open(),先檢查usage counter是否為0,如果是,將resource分配給device driver,並將counter+1. • 釋放resource時,呼叫release(),先檢查usage counter是否為null,如果不是counter-1,直到counter為null,就把resource釋放.
Monitoring I/O operations • The duration of an I/O operation is often unpredictable. • Two techniques • Polling mode • Interrupt mode
Polling mode • Simple example of polling for (; ;){ if (read_status(device) & DEVICE_END_OPERATION) break; if (--count == 0) break; } • If time to complete I/O operation is high • Voluntarily relinquish the CPU after each polling • Insert an schedule() function inside the loop
Interrupt mode • Only if the I/O controller can signal the end of I/O operation • 如果I/O device能夠通過IRQ line發出I/O操作結束信號,那麼interrupt mode才能被使用. • Interrupt handling 1. Process發出I/O request 2. CPU設定I/O controller命令 3. Process進入 waiting state,此時CPU可切換給其他process使用 4. 當I/O運做完成, I/O controller會發出 ”I/O complete”中斷通知OS 5. OS會暫停目前process執行,啟動對應的interrupt service routine執行 6. ISR completes, resume process execution. • Simple input character device • Issue read() system call on device file • foo_read() • Implement the read method of the file object • foo_interrupt() • Handle the interrupt