System V IPC (InterProcess Communication) Messages Queue, Shared Memory, and Semaphores Messages • Four system call – msgget( ), msgsnd( ), msgrcv( ), and msgctl( ) • msgqid = msgget(key, flag) – Create a new message queue (entry) or to retrieve an existing message queue – key: a name chosen by user, represent a message queue. – Flag: such as create flag bit with different permission – Return a kernel –chosen descriptor which points to the message queue • Each message queue (or IPC entry) has a permissions structure – Pointers to the first and last messages on a linked list – The number of messages and the total number of data bytes on the linked list – The process ID of the last processes to send and receive messages – Time stamps of the last msgsnd, msgrc, and msgctl operation • msgsnd (msgqid, msg, count, flag) • count = msgrcv(id, msg, maxcount, type, flag) – Id: message descriptor – Msg: the address of a user structure (message) – Maxcount: the size of the msg – Type: the message type that user wants to read – Flag: specifies what the kernel should do if no message are on the queue – Count: the number of bytes returned to the user • Msgctl(id, cmd, mstatbuf) – Query the status of a message descriptor, set its status, and remove a message queue Shared Memory • Shmget: create a new region of shared memory or returns an existing one – Shmid = shmget (key, size, flag) • Shmat: logically attacheds a shared memory to the virtual address space of a process – Virtaddr = shmat (id, addr, flags) • Shmdt: detaches a shared memory from the virtual address – Shmdt(addr) • Shmctl: manipulate various parameters associated with the shared memory – Shmctl9id, cmd, shmstatbuf) Semaphores • Id=semget (key, nsems, flag) – nsems: represent the number of the semaphore element • Oldval = Semop(id, oplist, nsops) – Oplist: point to an array of semaphore operation • include sem_num, operation (positive or negative), flag – Nsops: indicate the size of operation array – Oldval: the value of the semaphore before operation • The kernel change the value of a semaphore according to the value of the operation – Operation = 0, if element is 0, continue, else sleep – Operation is positive: increase the semaphore, awaken all process that are waiting the semaphore – Operation is negative: • if operation + element > 0, element – operation, and continue • If operation + element < 0, sleep • If operation + element = 0, wakeup a process which wait the element to 0 • Semctl(id, number, cmd, arg) – Number: the number of semaphore elements required to do the cmd operation – Cmd: retrieve or set control parameters (permissions and others) – Set one or all semaphore values in a set – Read the semaphore values – Arg: is interpreted based on the value of cmd. Union semunion{ int val; struct semid_ds *semstat; unsigned short *array; }arg; The program is a.out User executes it three times In the following sequence: a.out & a.out a & a.out b & Undo flag • Dangerous situations could occur – If a process does a semaphore operation, locking some resource, and then exit without resetting the semaphore value (ex: program error, receipt a signal, sudden termination, core down) • To avoid such problems – Process can set the SEM_UNDO flag in the semop call; when it exits, the kernel reverses the effect of every semaphore operation the process has done. ptrace(cmd, pid, addr, data) • Cmd: read/write data, .. • Addr: a virtual address to be read/written in the traced process • Data: an integer value to be written (write to addr) • P42: how do system calls actually work? – Use interrupt 0x80 which provides the argument of sys_call_num and sys_call_args – If the process which PF_TRACESYS is set (means traced process), the system call sends a SIGTRAP signal to the parent process and calls the scheduler. The traced process is interrupted until the parent process reactivates it (the ptrace() system call is called again) • pid = Fork() system call – Only way for a user to create a new process – The return of the fork system call • In the parent process, pid is the child process ID • In the child process, pid is 0 – Kernel does the following sequence of operations for fork • Allocate a slot in the process table for the new process • Assign a unique ID number to the child process • Make a logical copy of the context of the parent process (text region is shared between the parent and child process). • Increment file and inode table counters for files associated with the process • Return the ID number of the child to the parent process, and a 0 value to the child process Process tracing • Debugger forks a child process • Child process invokes the ptrace system call thus kernel sets a trace bit in the child process table entry • The child process execs the traced program • The kernel executes the exec call – Due to the trace-bit is set, the kernel sends the “trap” signal to the parent which wake up the parent from the wait call. • The parent call ptrace to do the read/write operation of the traced process • The traced process wakeup and do the operation of ptrace call and continue execution until execute the system call