Standard C LibraryImportant File I/O FunctionsUNIX ‘man’ pagesThe ‘open’ functionThe ‘close’ functionThe ‘read’ functionThe ‘write’ functionDefault is ‘Blocking’ ModeHow system-calls workHow multitasking worksTasks have various ‘states’Kernel manages tasksSpecial ‘wait’ queuesHow to use Linux wait-queues‘interruptible’ wait-queuesA convenient ‘macro’‘stash’: a character deviceRingbufferRingbuffer (continued)write-algorithm for ‘stash’read-algorithm for ‘stash’Demonstration of ‘stash’Standard C LibraryApplication Programming Interface to System-CallsImportant File I/O Functions•int open( char *pathname, int flags ); •int read( int fd, void *buf, size_t count ); •int write( int fd, void *buf, size_t count ); •int close( int fd );UNIX ‘man’ pages•A convenient online guide to prototypes and semantics of the C Library Functions •Example of usage:$ man 2 openThe ‘open’ function•#include <fcntl.h>•int open( const char *pathname, int flags );•Converts a pathname to a file-descriptor•File-descriptor is a nonnegative integer •Used as a file-ID in subsequent functions•‘flags’ is a symbolic constant: O_RDONLY, O_WRONLY, O_RDWRThe ‘close’ function•#include <unistd.h>•int close( int fd );•Breaks link between file and file-descriptor•Returns 0 on success, or -1 if an errorThe ‘read’ function•#include <unistd.h>•int read( int fd, void *buf, size_t count );•Attempts to read up to ‘count’ bytes•Bytes are placed in ‘buf’ memory-buffer•Returns the number of bytes read•Or returns -1 if some error occurred•Return-value 0 means ‘end-of-file’The ‘write’ function•#include <unistd.h>•int write( int fd, void *buf, size_t count );•Attempts to write up to ‘count’ bytes•Bytes are taken from ‘buf’ memory-buffer•Returns the number of bytes written•Or returns -1 if some error occurred•Return-value 0 means no data was writtenDefault is ‘Blocking’ Mode•Special considerations for device-files•The ‘read()’ function normally does not return 0 unless ‘end-of-file’ is reached•Devices expected to have more data soon •But on multitasking system: waiting is bad!How system-calls workApplication ProgramUser-space Kernel-spaceC Runtime LibraryOperating System KernelDevice DriverHow multitasking works•Can be ‘cooperative’ or ‘preemptive’•‘interrupted’ doesn’t mean ‘preempted’•‘preempted’ implies a task was switched•‘task-switching’ implies a context-changeTasks have various ‘states’•A task may be ‘running’•A task may be ‘ready-to-run’•A task may be ‘blocked’Kernel manages tasks•Kernel uses ‘queues’ to manage tasks•A queue of tasks that are ‘ready-to-run’•Other queues for tasks that are ‘blocked’Special ‘wait’ queues•Need to avoid wasteful ‘busy waiting’•So Device-Drivers can put tasks to sleep•And Drivers can ‘wake up’ sleeping tasksHow to use Linux wait-queues•#include <linux/sched.h>•wait_queue_head_t my_queue;•init_wait_queue_head( &my_queue );•sleep_on( &wq );•wake_up( &wq );•But can’t unload driver if task stays asleep!‘interruptible’ wait-queues•Device-driver modules should use:interruptible_sleep_on( &my_queue );wake_up_interruptible( &my_queue );•Then tasks can be awakened by interruptsA convenient ‘macro’ •DECLARE_WAIT_QUEUE_HEAD( wq );•This statement can be placed outside yourmodule’s functions•It combines declaration and initialization:wait_queue_head_t wq;init_wait_queue( &wq );‘stash’: a character device•Device works like a public ‘clipboard’•It uses kernel memory to store its data•It allows ‘communication’ between tasks•What one task writes, another can read!Ringbuffer •A first-in first-out data-structure (FIFO)•Uses a storage array of finite length•Uses two array-indices: ‘head’ and ‘tail’•Data is added at the current ‘tail’ position•Data is removed from the ‘head’ positionRingbuffer (continued)•One array-position is always left unused•Condition head == tail means “empty”•Condition tail == head-1 means “full”•Both ‘head’ and ‘tail’ will “wraparound”•Calculation: next = ( next+1 )%RINGSIZE;write-algorithm for ‘stash’•while ( ringbuffer_is_full ) {interruptible_sleep_on( &wq );If ( signal_pending( current ) ) return –EINTR;}•Insert byte from user-space into ringbuffer;•wake_up_interruptible( &wq );•return 1;read-algorithm for ‘stash’•while ( ringbuffer_is_empty ) {interruptible_sleep_on( &wq );If ( signal_pending( current ) ) return –EINTR;}•Remove byte from ringbuffer and store to user-space;•wake_up_interruptible( &wq );•return 1;Demonstration of ‘stash’•Quick demo: we can use I/O redirection•For demonstrating ‘write’ to /dev/stash:$ echo “Hello” > /dev/stash•For demonstrating ‘read’ from /dev/stash:$ cat
View Full Document