500 likes | 601 Views
rtl_posixio Kernel Module. 928316 方國州. Outline. Introduction POSIX standard Code trace. Operating System Services. Base Standards System API Shell and Utilities System Administration. POSIX.
E N D
rtl_posixio Kernel Module 928316 方國州
Outline • Introduction • POSIX standard • Code trace
Operating System Services • Base Standards • System API • Shell and Utilities • System Administration
POSIX • POSIX (the ”Portable Operating System Interface”) is a specification which dictates how operating systems should behave. Among other things, it specifies basic operations involving signaling and threads, making it easier for programmers to port their applications from one operating system to the other.
POSIX Interfaces • Extensions • System API Extensions • Real Time and Related API • Threads API • Real Time Extensions • Security • Additional Utilities • Protection and Control Utilities
POSIX in RTLinux • RTLinux API is based on a small system POSIX “profile” that is specified in POSIX standards 1003.13 PSE51. • This profile is for a ”minimal real-time system” environment and it looks very much like a multithreaded single POSIX process.
Real time API Interfaces • Real time API interfaces of POSIX • Preemptive Scheduling • Priority Interrupts • High Performance File System • Nanosecond Timers
I/O in Linux • The same system calls for regular files can be used for I/O devices • The function costs lots time to deal with INODE structure. • POSIX standard permit a very limited version of open. • INODE structure is ignored • A file may be access by several processes at the same time • Need file object structure to record some information for a opened file.
I/O device • Block Device • Allow random access • Fixed size of block • Ex: HD , CD-ROM , Floppy • Character Device • Do not need to support all functionality of regular files • Ex: most other devices • The device serviced by RTLinux device driver only can be a character device
POSIXIO • Linux has difficulty on OPEN for supporting POSIXIO • Open in a file system is inherent non-real time • Opening a device file may require an unbounded time for • traversal of the namespace • following symbolic links • Resolving directories • Cross mount point
Code Trace • Version:rtlinux-3.2-pre2 • Basic operation • rtl_register_rtldev • rtl_unregister_rtldev • Function calls • open • close • read • write • mmap / munmap • ioctl
Data structure • static struct rtl_file rtl_files [MAX_RTL_FILES] = { { NULL, 0 },}; • struct rtl_file{struct rtl_file_operations *f_op; • int f_minor; • int f_flags; • rtl_files • loff_t f_pos; • }; max_rtl_files=128
Register device • int rtl_register_rtldev(unsigned int major, const char * name,struct rtl_file_operations *fops) • { • if (major >= MAX_CHRDEV) • return -EINVAL; • if(rtldevs[major].fops &&rtldevs[major].fops != fops) { • return -EBUSY; • } • rtldevs[major].name = name; • rtldevs[major].fops = fops; • return 0; • }
Unregister device • int rtl_unregister_rtldev(unsignedintmajor, const char * name) • { • if (major >= MAX_CHRDEV) • return -EINVAL; • if (!rtldevs[major].fops) • return -EINVAL; • if(strcmp(rtldevs[major].name, name)) • return -EINVAL; • rtldevs[major].name = NULL; • rtldevs[major].fops = NULL; • return 0; • }
Open • open() will only open files named /dev/filenameNN where filename is the name provided to the register call by the driver and NN is an optional device minor number
rtl_devs 5 Xforce ……………. ……………. …………….. Xforce Open_l Open_r Open_f Read_l Read_r Read_f Write_l Write_r Write_f Register a Deivce rtl_register_rtldev(5,”Xforce”,****)
task1 open(“/dev/Xforce3”) C=read(7,buf,128) open(“/dev/Xforce4”) C=read(8,buf,1024) task2 open(“/dev/Xforce5”) C=write(9,buf,128) task3 devname rtl_devs Open_r 7 Xforce3 5 Xforce Read_r 8 Xforce4 ……………. Write_r 9 Xforce5 ……………. …………….. …………….. Open a file
Open • int open(const char *pathname, int flags) • { int i; • int minor; • int major; • char devname[200]; • char *p; • int ret; • if (strncmp(pathname, "/dev/", 5)) { • __set_errno(ENOENT); • return -1; • } • i = 0; • while (i < sizeof(devname) - 1 && *(pathname + 5 + i) && !isdigit(*(pathname + 5 + i)) • { devname[i] = *(pathname + 5 + i); • i++; • } • devname[i] = 0;
Open • if (isdigit(*(pathname + 5 + i))) { • minor = simple_strtoul (pathname + 5 + i, &p, 10); • } • else if (!*(pathname + 5 + i)) { • minor = 0; } • else { • __set_errno(ENOENT); • return -1; } • for (i = 0; i < MAX_CHRDEV; i ++) { • if (rtldevs[i].name && !strcmp(rtldevs[i].name, devname)) • { goto found_major; } } • rtl_printf("rtl_posixio: dev entry %s not found\n", pathname); __set_errno(ENOENT); • return -1;
Open (found_major) • found_major: • major = i; • for (i = 0; i < MAX_RTL_FILES; i ++) { • if (!rtl_files[i].f_op) { • goto found_free; } } • __set_errno(ENOMEM); • return -1;
Open(found_free) • found_free: • rtl_files[i].f_op = rtldevs[major].fops; • rtl_files[i].f_minor = minor; • rtl_files[i].f_flags = flags; • ret = rtl_files[i].f_op->open(&rtl_files[i]); • if (ret < 0) { • rtl_files[i].f_op = NULL; • rtl_files[i].f_minor = 0; • rtl_files[i].f_flags = 0; • __set_errno(-ret); • return -1; } • return i; • }
Close • int close(int fd){ • CHECKFD(fd); • rtl_files[fd].f_op->release(&rtl_files[fd]); • rtl_files[fd].f_op = NULL; • return 0;} • CHECKFD(fd) • if ((unsigned int) (fd) >= MAX_RTL_FILES || !rtl_files[fd].f_op) { • __set_errno(EBADF); • return -1; • }
Read • ssize_t read(int fd, void *buf, size_t count){ • int ret; • CHECKFD(fd); • ret = rtl_files[fd] . f_op -> read (&rtl_files[fd], buf, count, &rtl_files[fd].f_pos); • if (ret < 0) { • __set_errno(-ret); • return -1; } • return ret;}
Write • ssize_t write(int fd, const void *buf, size_t count){ • int ret; • CHECKFD(fd); • ret = rtl_files[fd] . f_op -> write (&rtl_files[fd], buf, count, &rtl_files[fd].f_pos); • if (ret < 0) { • __set_errno(-ret); • return -1; } • return ret;}
MMAP • caddr_t mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset){ • int ret; • caddr_t result; • if ((unsigned int) (fd) >= MAX_RTL_FILES || !rtl_files[fd].f_op) { • __set_errno(EBADF); • return (caddr_t) -1; } • if (! rtl_files[fd] . f_op -> mmap) { • __set_errno(EINVAL); • return (caddr_t) -1; } • ret = rtl_files[fd] . f_op -> mmap (&rtl_files[fd], start, length, prot, flags, offset, &result); • if (ret != 0) { • __set_errno(-ret); • return (caddr_t) -1; } • return result;}
MUNMAP • int munmap(void *start, size_t length){ • iounmap (start); • return 0;}
IOCTL • int ioctl(int fd, int request, ...){ • int ret; • va_list list; • unsigned long arg; • va_start (list, request); • arg = va_arg(list, unsigned long); • va_end (list); • CHECKFD(fd); • ret = rtl_files[fd] . f_op -> ioctl (&rtl_files[fd], request, arg); • if (ret < 0) { • __set_errno(-ret); • return -1; } • return 0;}
RTLinux dev/mem support • This driver allows real-time threads to access physical computer memory in the same way as Linux processes can do. • dev/mem sopport is optinal. • Related functions • init_module • cleanup_module • rtl_mem_open • rtl_mem_release • rtl_mem_write • rtl_mem_read • rtl_mem_mmap • rtl_mem_llseek
Init/cleanup/open/release dev/mem • static int rtl_mem_open (struct rtl_file *filp){ • return 0;} • static int rtl_mem_release (struct rtl_file *filp){ • filp->f_pos = 0; • return 0;}
Read/write in dev/mem • static ssize_t rtl_mem_write(struct rtl_file *filp, const char *buf, size_t count, loff_t* ppos){ • memcpy_toio ((long) *ppos, buf, count); • *ppos += count; • return count; • } • static ssize_t rtl_mem_read(struct rtl_file *filp, char *buf, size_t count, loff_t* ppos){ • memcpy_fromio (buf, (long) *ppos, count); • *ppos += count; • return count; • }
rtl_mem_mmap • static int rtl_mem_mmap (struct rtl_file *file, void *start, size_t length, int prot , int flags, off_t offset, caddr_t *result){ • if (!rtl_rt_system_is_idle()) { • return -EAGAIN; • } • *result = ioremap (offset, length); • if (!*result) { • return -EINVAL; • } • return 0; • }
rtl_mem_llseek • static loff_t rtl_mem_llseek(struct rtl_file *file, loff_t offset, int origin){ • if (origin != SEEK_SET) { • return -EINVAL; • } • return file->f_pos = offset; • }
The Goal of real-time guarantees • 3 components • IDE driver • Porting from linux IDE driver • Does not support ATAPI and Others • DMA mode is supported • Does not support request in separated address • Real-time file system • Real-time disk schedular
Buffer and Cache • The linux IDE driver support buffer and page cache. • The block buffer keep the data in writing, and read forward for sequential access. • The block buffer are not suitable in real-time and streaming application. The buffer is removed in the porting
DMA Mode Support • In IDE interface, the DMA mode has a unreachable bandwidth to the PIO mode. • The driver checks to do during initialization • Is the IDE Disk present? • Is a Master DMA and LBA capable disk? • Is disk into the devices black list? • What DMA mode is supporter? • The initialization is done in linux boot time. RTlinux only needs the structure in linux.
Disk scheduler and file system • The disk scheduler and file system do not change any code in rtlinux kernel • The disk scheduler only sort the priority of requested thread. The mutex semaphores are used for synchronization • The file system needs to support concurrency and simplicity
file system • Space Allocation • How data is allocated • How meta-data is managed • Buffer Cache • Cache drawbacks: extra copy, crash, few data, • Large buffer cache is unnecessarily, only 512 bytes per file • Reliability • Log (or journal ) structured
File system • Portability • should be used in linux • User Buffer Allocation • Map directly to device, not system buffer • rtlinux memory allocation do not handle DMA address property, must allocated in boot time • Read and Write function • In posix, the caller task will be blocked
File system • Read and Write division • One task reads data and other writes data to disk, sharing a buffer • Trusted Enviroment • No access protection code • FAT is suitable for real-time file systems
Real-time file system Specification • Super Block: layout of the file system • INODES TABLE: limited in 1638 file (64KB size) • EXTENTX TABLE : 16384 extents (64KB size)
Extents table is a linked list structure • Extents Reliability • Reliability sector ahead to every extends
Extents • timestamp :compared in superblock • previous_extent • bytes • buff[]
The File system limits • The maximum size of a file is 2^64 bytes. • The maximum number of extents per file is not limited. • Maximum number of files: 1638. • Maximum number of extents: 16384
Related Tools of the file system • mkfs.rtlfs: build a rtlfs • rtlfs.chk :repair and check a rtlfs • Linux Module : mount in linux, read only • rtl_register_fs :register RT file systems • rtl_mount