120 likes | 153 Views
This article explores various methods of interprocess communication and resource sharing in the kernel, including data structures, buffers, shared memory, files, synchronization methods, and signals.
E N D
Resource Sharing • Kernel: Data structures, Buffers • Processes: Shared Memory, Files • Synchronization Methods • Kernel: Wait Queues, Semaphores • Processes: Semaphores, file locks • Data Exchange: • Kernel: Signals • Processes: Signals, Message Queues, Sockets, Pipes
Kernel Synchronization Struct wait_queue { Struct task_struct *task; Struct wait_queue *next; } Add_wait_queue(struct wait_queue **p, struct wait_queue *wait) { Unsigned long flags; Save_flags(flags); Cli(); __add_wait_queue(p,wait); // actual insert Restore_flags(flags); } Remove_wait_queue(….) { … }
Semaphores within Kernel Struct semaphore { int count, waiting; struct wait_queue *wait; } down(struct semaphore *psem) { while (--psem->count <= 0) { psem->waiting++; if (psem->count + psem->waiting <= 0) { do sleep(psem->wait) while (psem->count < 0); } psem->count += psem->waiting; psem->waiting = 0; } } More complicated due to race conditions and not turning off interrupts
File Locking • Locking Entire Files • Auxiliary file (lock file) – if it exists, lock fails. You can then sleep and retry. • Using fcntl() system call. • Locking file areas • Using fcntl()
int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); • Cmd = FGET_LK (returns if locked or not), F_SET_LK (tries to lock, else returns), F_SETLKW (locks, else blocks) • Arg = pointer to a flock. Struct flock { Short l_type; // F_RDLCK, F_WRLCK, F_UNLCK, F_SHLCK, F_EXLCK Short l_whence; // SEEK_SET (file start), SEEK_CUR, SEEK_END Off_t l_start; Off_t l_len; //0 indicates current and future end of file Pid_t pid; };
Doubly linked list file_lock_table is used Struct file_lock { Struct file_lock *fl_next; // singly linked for this inode Struct file_lock *fl_nextlink, *fl_prevlink; // across all inodes Struct task_struct *fl_owner; Struct wait_queue *fl_wait; Struct file *fl_file; Off_t fl_start, fl_end; } Struct file_lock *file_lock_table; • Linux tracks down deadlocks and returns EDEADLK • Locks are not transferred to child by fork but are retained in exec
Pipes mkfifo <pathname> Or mknod <pathname> p ls –l > fifo & more < fifo
Struct pipe_inode_info { Struct wait_queue *wait; Char *base; // address of FIFO bounded buffer Unsigned int start; Unsigned int len; Unsigned int lock; Unsigned int rd_openers; Unsigned int wr_openers; Unsigned int readers; // currently reading Unsigned int writers; // currently writing } • Read/Write will not block if O_NONBLOCK is set in descriptor. • Write operation is atomic (no intermixing of writes) as long as data does not exceed buffer size.
Debugging Int sys_ptrace(long request, long pid, long addr, long data) Request = PTRACE_TRACEME // trace me PTRACE_ATTACH // to trace child PTRACE_PEEKTEXT/PEEKDATA // to examine locns. PTRACE_POKETEXT/POKEDATA // to write PTRACE_CONT // to continue the child PTRACE_SYSCALL // continue until next sys call PTRACE_SINGLESTEP
How does gdb work? • Forks a child process • Child calls function with PTRACE_TRACEME • Child then does an execve() on the program • The execve call sebds a SIGTRAP to itself. • In the handler, the process is halted, and parent is informed with SIGCHLD signal. • Parent (debugger) waits for this signal using wait() • It can inspect child memory, modify it, set breakpoints (int 3 instruction) • It requests PTRACE_CONT, child continues till trapping on an int 3 instruction. • strace simply uses PTRACE_SYSCALL
System V IPC Support • IPC permissions Struct ipc_perm { Key_t key; // using file name and char Ushort uid, gid; // owner Ushort cuid, cgid; // creator Ushort mode; // access modes } • Semaphores • Message Queues • Shared Memory • Sockets