1 / 70

IPC- InterProcess Communication

IPC- InterProcess Communication. 939607 張佑竹 9662637 林其翰 9662658 馮秉森 9664522 李立偉. System V IPC. IPC (Interprocess Communication) commonly refers to a set of mechanisms that allow a User Mode process to do the following: Send messages to other processes or receive messages from them.

dunne
Télécharger la présentation

IPC- InterProcess Communication

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. IPC-InterProcess Communication 939607 張佑竹 9662637 林其翰 9662658 馮秉森 9664522 李立偉

  2. System V IPC • IPC (Interprocess Communication) commonly refers to a set of mechanisms that allow a User Mode process to do the following: • Send messages to other processes or receive messages from them. • Synchronize itself with other processes by means of semaphores. • Share a memory area with other processes.

  3. Message

  4. Data Structure • msg_ids • msg_queue • msg_msg • msg_msgseg • msg_receiver • msg_sender

  5. Data Structure • IPC message queue data structures

  6. msg_ids static struct ipc_ids msg_ids; // ipc/msg.c line 69 struct ipc_ids { // ipc/util.h line 33 int in_use; unsigned short seq; unsigned short seq_max; struct rw_semaphorerw_mutex; struct idripcs_idr; };

  7. msg_queue // include/linux/msg.hline 78 structmsg_queue{ structkern_ipc_permq_perm; time_tq_stime; // Time of last msgsnd( ) time_tq_rtime; // Time of last msgrcv( ) time_tq_ctime; // Last change time unsigned long q_cbytes; // Current bytes in queue unsigned long q_qnum; // Number of messages in queue unsigned long q_qbytes; // Max number of byte in queue pid_tq_lspid; // PID of last msgsnd( ) pid_tq_lrpid; // PID of last msgrcv( ) structlist_headq_messages;//List of messages in queue structlist_headq_receivers; // List of processes receiving messages structlist_headq_senders; // List of processes sending messages };

  8. msg_msg // include/linux/msg.h 68 struct msg_msg{ structlist_headm_list;// Pointers for message list longm_type;// Message type intm_ts;/* message text size */ structmsg_msgseg*next; //Next portion of the message void*security; //Pointer to a security data structure (used by SELinux) //The actual message follows immediately };

  9. msg_msgseg // ipc/msgutil.c line 20 structmsg_msgseg { structmsg_msgseg* next; /* the next part of the message follows immediately*/ };

  10. msg_receiver // ipc/msg.c line 47 structmsg_receiver { structlist_head r_list; // A link list for all msg_receiver struct task_struct* r_tsk; int r_mode; long r_msgtype; long r_maxsize; structmsg_msg *volatile r_msg; };

  11. msg_sender // ipc/msg.c line 59 structmsg_sender { struct list_head list; // A link list for all msg_sender structtask_struct *tsk; // Pointer to process structure which is waiting for receiving messages };

  12. Functions • sys_msgget() • newque() • sys_msgctl() • sys_msgsnd() & do_msgsnd() • load_msg() • pipelined_send() • sys_msgrcv() &do_msgrcv()

  13. sys_msgget() // ipc/msg.c line 313 • Allocate a new message queue, or access to an existing message queue again. • Flags • IPC_CREAT:A new queue will be created if it is not yet created → newque() • IPC_EXCL:If IPC_CREAT is set and such a queue exists, the function will return with the error EEXIST.

  14. sys_msgget() no OK T key=IPC_PRIVATE? msg_ids is full? (newqueue) yes ERROR F T no key is exist? msgflg & IPC_CREAT yes F ENOENT msgflg & IPC_CREAT && msgflg & IPC_EXCL ? T EEXIST ERROR msq=msg_lock() ipcperm(msgflg) EACCES msg_buildid OK

  15. newque() // ipc/msg.c line 181 failure ipc_rcu_alloc (struct msg_queue) ENOMEM OK id==-1 id=ipc_addid() ipc_rcu_free id!=-1 set initial value ENOSPC msg_buildid (IPCMNI*seq + id) OK

  16. sys_msgctl() // ipc/msg.c line 424 • IPC_INFO:Copy some message queue information to user space from kernel space. • IPC_STAT:Copy some message queue states to user space from kernel space. • IPC_SET:Modify values of message queue objects. • IPC_RMID:Remove all associated message queue structure.

  17. sys_msgsnd() & do_msgsnd() // ipc/msg.c line 752 longsys_msgsnd(….){ long mtype; if (get_user(mtype, &msgp->mtype)) return -EFAULT; returndo_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg); }

  18. sys_msgsnd() & do_msgsnd() T // ipc/msg.c line 661 msgsz > ns->msg_ctlmax || msgsz < 0 || msqid < 0 ERROR F F msg = load_msg() PTR_ERR(msg) F msq = msg_lock() EINVAL F msg_checkid, ipcperm ERROR EINTER EAGAIN msgsz + q_cbytes > q_qbytes || q_qnum +1 > q_qbyte T F T T F msgflg & IPC_NOWAIT Update q_lspid ,q_stime Check signal_pending F OK Add to q_senders pipelined_send() Remove from q_senders No one is waiting OK msq=msg_lock() call schedule() Add to q_messages F EIDRM END

  19. load_msg() ……….

  20. load_msg() // ipc/msgutil.c line 28 while (len > 0) { struct msg_msgseg *seg; alen = len; if (alen > DATALEN_SEG) alen = DATALEN_SEG; seg = kmalloc(sizeof(*seg) + alen, GFP_KERNEL); if (seg == NULL) { err = -ENOMEM; goto out_err; } *pseg = seg; seg->next = NULL; if (copy_from_user(seg + 1, src, alen)) { err = -EFAULT; goto out_err; } pseg = &seg->next; len -= alen; src = ((char __user *)src) + alen; }

  21. pipelined_send() msr=msg_receiver.r_list testmsg(r_msgtype, r_mode) OK F Delete msr r_maxsize < msg->m_ts T F r_msg=E2BIG r_msg=msg wakeup r_tsk wakeup r_tsk T FOUND next msg_receiver F END

  22. sys_msgrcv() &do_msgrcv() F msqid<0 || msqsz<0 msg=msg_lock() T F OK EINVAL F ERROR ipcperms OK T msq->q_messages.next != &msq->q_messages testmsg() F F T found_msg F T add to q_receivers msgflg & IPC_NOWAIT msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR ENOMSG schedule() F Check has_messages Remove found_msg rcu_read_lock() F T wakeup q_senders Check signal_pending F T END put msg to user space EINTR OK F EFAULT

  23. Semaphore

  24. Data Structure • init_sem_ids • sem • sem_array • sem_queue • sem_undo

  25. Data Structure

  26. Data Structure • init_sem_ids • sem • sem_array • sem_queue • sem_undo

  27. init_sem_ids static struct ipc_ids init_sem_ids; //ipc/sem.c line 95 structipc_ids { //ipc/util.h line 31 int in_use; unsigned short seq; unsigned short seq_max; structrw_semaphore rw_mutex; structidr ipcs_idr; };

  28. Data Structure • init_sem_ids • sem • sem_array • sem_queue • sem_undo

  29. sem structsem { //include/linux/sem.h line 85 int semval; //current value int sempid; //pid of last operation };

  30. Data Structure • init_sem_ids • sem • sem_array • sem_queue • sem_undo

  31. sem_array structsem_array { //include/linux/sem.h line 91 structkern_ipc_perm sem_perm; //permissions time_t sem_otime; //last semop time time_t sem_ctime; //last change time structsem *sem_base; //ptr to first semaphore in array struct sem_queue *sem_pending; //pending operations to be processed structsem_queue **sem_pending_last; //last pending operation structsem_undo *undo; //undo requests on this array unsigned long sem_nsems; //no. of semaphores in array };

  32. Data Structure • init_sem_ids • sem • sem_array • sem_queue • sem_undo

  33. sem_queue structsem_queue { //include/linux/sem.h line 103 structsem_queue *next; //next entry in the queue structsem_queue **prev; //previous entry in the queue, *(q->prev) == q structtask_struct *sleeper; //this process structsem_undo *undo; //undo structure int pid; //process id of requesting process int status; //completion status of operation structsem_array *sma; //semaphore array for operations int id; //internal sem id struct sembuf *sops; //array of pending operations int nsops; //number of operations int alter; //does the operation alter the array? };

  34. Data Structure • init_sem_ids • sem • sem_array • sem_queue • sem_undo

  35. sem_undo struct sem_undo { //include/linux/sem.h line 120 structsem_undo *proc_next; //next entry on this process structsem_undo *id_next; //next entry on this semaphore set int semid; //semaphore set identifier short *semadj; //array of adjustments, one per semaphore };

  36. Functions • sys_semget() • newary() • sys_semctl() • semctl_nolock() • semctl_main() • semctl_down() • sys_semop() • sys_semtimedop() • update_to_queue()

  37. sys_semget() // ipc/sem.c line 335 • Allocate a new semaphore, or access to an existing semaphore again. • Flags • IPC_CREAT:A new semaphore will be created if it is not yet created → newary() • IPC_EXCL:If IPC_CREAT is set and such a semaphore exists, the function will return with the error EEXIST.

  38. sys_semget() no OK T key=IPC_PRIVATE Init_sem_ids is full? (newary) yes ERROR F T no key is exist? semflg & IPC_CREATE yes F ENOENT semflg & IPC_CREATE && semflg & IPC_EXCL ? T EEXIST T ERROR sma=sem_lock() T ipcperm(semflg) EACCES sem_buildid OK

  39. newary() // ipc/sem.c line 255 failure ipc_rcu_alloc (struct aem_array) ENOMEM OK id==-1 id=ipc_addid() ipc_rcu_free id!=-1 set initial value ENOSPC sem_buildid (IPCMNI*seq + id) OK

  40. sys_semget() asmlinkagelong sys_semget (key_t key, int nsems, int semflg) { // ipc/sem.c line 335 if (nsems < 0 || nsems > ns->sc_semmsl) return -EINVAL; if (key == IPC_PRIVATE) { newary(); }else if ((id = ipc_findkey(&sem_ids(ns), key)) == -1) { if (!(semflg & IPC_CREAT)) err = -ENOENT; else newary(); }else if (semflg & IPC_CREAT && semflg & IPC_EXCL) { err = -EEXIST; }else //other code }

  41. Functions • sys_semget() • newary() • sys_semctl() • semctl_nolock() • semctl_main() • semctl_down() • sys_semop() • sys_semtimedop() • update_to_queue()

  42. sys_semctl() // ipc/sem.c line 967 true cmd = IPC_INFO ? cmd = SEM_INFO ? cmd = SEM_STAT ? failure semctl_nolock cmd = GETALL ? cmd = GETVAL ? cmd = GETPID ? cmd = GETNCNT ? cmd = GETZCNT ? cmd = IPC_STAT ? cmd = SETVAL ? cmd = SETALL ? true semctl_main semctl_main failure true cmd = IPC_RMID ? cmd = IPC_SET ? failure EINVAL

  43. semctl_nolock() staticint semctl_nolock(structipc_namespace *ns, int semid, int semnum, int cmd, int version, union semun arg) { // ipc/sem.c line 610 switch(cmd) { case IPC_INFO: case SEM_INFO: …… return (max_id < 0) ? 0: max_id; case SEM_STAT: …… return id; default: return -EINVAL; } }

  44. semctl_main() if(semnum < 0 || semnum >= nsems) goto out_unlock; case GETVAL: // sem_base[semnum].semval case GETPID: // sem_base[semnum].sempid case GETNCNT: // count_semncnt() case GETZCNT: // count_semzcnt() case SETVAL: // set sem_case[semnum] default: err = -EINVAL; } sem_unlock(sma); } staticint semctl_main(structipc_namespace *ns, int semid, int semnum,int cmd, int version, union semun arg) { // ipc/sem.c line 689 sma = sem_lock_check(ns, semid); switch (cmd) { case GETALL: // get sem_base[] value case SETALL: // set sem_base[] value case IPC_STAT: // get semid64_ds

  45. semctl_down() staticint semctl_down(structipc_namespace *ns, int semid, int semnum, int cmd, int version, union semun arg) { // ipc/sem.c line 904 if(cmd == IPC_SET) if(copy_semid_from_user (&setbuf, arg.buf, version)) return -EFAULT; sma = sem_lock_check_down(ns, semid); switch(cmd){ case IPC_RMID: freeary(ns, sma); case IPC_SET: //update uid, gid, mode default: err = -EINVAL; } sem_unlock(sma); }

  46. Functions • sys_semget() • newary() • sys_semctl() • semctl_nolock() • semctl_main() • semctl_down() • sys_semop() • sys_semtimedop() • update_to_queue()

  47. sys_semop() asmlinkagelong sys_semop (int semid, structsembuf __user *tsops, unsigned nsops) { // ipc/sem.c line 1288 return sys_semtimedop(semid, tsops, nsops, NULL); }

  48. sys_semtimedop() return = 0 < 0 Do checks return update_queue() > 0 try_atomic_semop() return error return append_to_queue()

  49. sys_semtimedop() asmlinkagelong sys_semtimedop(int semid, struct sembuf __user *tsops, unsigned nsops, const structtimespec __user *timeout) {// ipc/sem.c line 1122 sma = sem_lock_check(ns, semid); // do checks error = try_atomic_semop (sma, sops, nsops, un, task_tgid_vnr(current)); if (error == 0) update_queue (sma); else if (error > 0) append_to_queue(sma ,&queue); // do checks sem_unlock(sma); return error; }

More Related