minix中进程相关知识
MINIX3本身是一组进程的集合。 其层次如下图 进程优先级随着层次的降低而升高
二 minix 中进程相关的一些定义 结构
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/proc.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 05500 #ifndef PROC_H 05501 #define PROC_H 05502 05503 /* Here is the declaration of the process table. It contains all process 05504 * data, including registers, flags, scheduling priority, memory map, 05505 * accounting, message passing (IPC) information, and so on. 05506 * 05507 * Many assembly code routines reference fields in it. The offsets to these 05508 * fields are defined in the assembler include file sconst.h. When changing 05509 * struct proc, be sure to change sconst.h to match. File: Page: 61 kernel/proc.h 05510 */ 05511 #include <minix/com.h> 05512 #include "protect.h" 05513 #include "const.h" 05514 #include "priv.h" 05515 05516 struct proc { 05517 struct stackframe_s p_reg; /* 进程保存在堆栈中的寄存器 process' registers saved in stack frame */ 05518 reg_t p_ldt_sel; /* 描述符表相关寄存器 selector in gdt with ldt base and limit */ 05519 struct segdesc_s p_ldt[2+NR_REMOTE_SEGS]; /* 代码段和数据段寄存器 CS, DS and remote segments */ 05520 05521 proc_nr_t p_nr; /* 进程编号 */ 05522 struct priv *p_priv; /* 特权结构体 */ 05523 char p_rts_flags; /* 进程的消息状态 SENDING, RECEIVING, etc. */ 05524 05525 char p_priority; /* 当前优先级。初始化与p_max_priority相同 */ 05526 char p_max_priority; /* 允许的最大优先级,表示一个进程首次处于就绪状态时需要放入哪个调试队列 */ 05527 char p_ticks_left; /* 进程剩余的时间片 */ 05528 char p_quantum_size; /* 分配给进程的时间片 */ 05529 05530 struct mem_map p_memmap[NR_LOCAL_SEGS]; /* 内存映射 memory map (T, D, S) */ 05531 05532 clock_t p_user_time; /* 用户时间滴答user time in ticks */ 05533 clock_t p_sys_time; /* 系统时间滴答sys time in ticks */ 05534 05535 struct proc *p_nextready; /* 指向下一个准备就绪的进程 */ 05536 struct proc *p_caller_q; /* 消息通信时指向要通信的进程链 head of list of procs wishing to send */ 05537 struct proc *p_q_link; /* 指向下一个要发送消息的进程 link to next proc wishing to send */ 05538 message *p_messbuf; /* 已发送消息缓冲区pointer to passed message buffer */ 05539 proc_nr_t p_getfrom; /* 等待接收消息的源进from whom does process want to receive? */ 05540 proc_nr_t p_sendto; /* 要发送消息的目的进程to whom does process want to send? */ 05541 05542 sigset_t p_pending; /* 信号位图bit map for pending kernel signals */ 05543 05544 char p_name[P_NAME_LEN]; /* 进程的名字name of the process, including \0 */ 05545 }; 05546 05547 /* Bits for the runtime flags. A process is runnable iff p_rts_flags == 0. */ 05548 #define SLOT_FREE 0x01 /* process slot is free */ 05549 #define NO_MAP 0x02 /* keeps unmapped forked child from running */ 05550 #define SENDING 0x04 /* 因为send消息而阻塞 process blocked trying to SEND */ 05551 #define RECEIVING 0x08 /* 因为接受消息而阻塞 process blocked trying to RECEIVE */ 05552 #define SIGNALED 0x10 /* set when new kernel signal arrives */ 05553 #define SIG_PENDING 0x20 /* unready while signal being processed */ 05554 #define P_STOP 0x40 /* set when process is being traced */ 05555 #define NO_PRIV 0x80 /* keep forked system process from running */ 05556 05557 /* Scheduling priorities for p_priority. Values must start at zero (highest 05558 * priority) and increment. Priorities of the processes in the boot image 05559 * can be set in table.c. IDLE must have a queue for itself, to prevent low 05560 * priority user processes to run round-robin with IDLE. 05561 */ //其中包括堆栈信息、段信息、寄存器等信息。对进程的优先级定义有以下宏 05562 #define NR_SCHED_QUEUES 16 /* 最大优先级数+1 MUST equal minimum priority + 1 */ 05563 #define TASK_Q 0 /* 内核任务拥有的最高优先级 highest, used for kernel tasks */ 05564 #define MAX_USER_Q 0 /* 用户进程用有的最高优先级 highest priority for user processes */ 05565 #define USER_Q 7 /* 默认优先级,对应的Nice为7 default (should correspond to nice 0) */ 05566 #define MIN_USER_Q 14 /* 用户进程拥有的最低优先级 minimum priority for user processes */ 05567 #define IDLE_Q 15 /* 最低优先级,只有IDLE lowest, only IDLE process goes here */ 05568 05569 /* Magic process table addresses. */ File: Page: 62 kernel/proc.h 05570 #define BEG_PROC_ADDR (&proc[0]) 05571 #define BEG_USER_ADDR (&proc[NR_TASKS]) 05572 #define END_PROC_ADDR (&proc[NR_TASKS + NR_PROCS]) 05573 05574 #define NIL_PROC ((struct proc *) 0) 05575 #define NIL_SYS_PROC ((struct proc *) 1) 05576 #define cproc_addr(n) (&(proc + NR_TASKS)[(n)]) 05577 #define proc_addr(n) (pproc_addr + NR_TASKS)[(n)] 05578 #define proc_nr(p) ((p)->p_nr) 05579 05580 #define isokprocn(n) ((unsigned) ((n) + NR_TASKS) < NR_PROCS + NR_TASKS) 05581 #define isemptyn(n) isemptyp(proc_addr(n)) 05582 #define isemptyp(p) ((p)->p_rts_flags == SLOT_FREE) 05583 #define iskernelp(p) iskerneln((p)->p_nr) 05584 #define iskerneln(n) ((n) < 0) 05585 #define isuserp(p) isusern((p)->p_nr) 05586 #define isusern(n) ((n) >= 0) 05587 05588 /* The process table and pointers to process table slots. The pointers allow 05589 * faster access because now a process entry can be found by indexing the 05590 * pproc_addr array, while accessing an element i requires a multiplication 05591 * with sizeof(struct proc) to determine the address. 05592 */ 05593 EXTERN struct proc proc[NR_TASKS + NR_PROCS]; /* 进程表 NR_PROCS可以更改,以创建一个能够处理更多进程的系统*/ 05594 EXTERN struct proc *pproc_addr[NR_TASKS + NR_PROCS]; 05595 EXTERN struct proc *rdy_head[NR_SCHED_QUEUES]; /* ptrs to ready list headers */ 05596 EXTERN struct proc *rdy_tail[NR_SCHED_QUEUES]; /* ptrs to ready list tails */ 05597 05598 #endif /* PROC_H */
发送:当一个进程 S 要发送消息给进程 D 时,内核先检测进程 D 是否准备接收进程 S 的消息(即进程 D 是否阻塞在接受进程 S 的消息上),如果是,则消息从进程 S 的内存空间上通过CopyMess 复制到进程 D 的内存空间上。内存空间的具体位置由 S 的进程描述符表( Proc )中的P_messbuf 指针所指定。如果进程 D 没有等待从消息 S 传递消息过来,那么进程 S 阻塞在给进程D 发送消息上 ,同时把自己加入到进程 D 中 p_caller_q 所指向的发送阻塞链表中。
三 进程间通讯:
SH3.1 首先了解下 进程间发送的消息的结构 定义在 ipc.h中
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/minix/ipc.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 03000 #ifndef _IPC_H 03001 #define _IPC_H 03002 03003 /*==========================================================================* 03004 * Types relating to messages. * 03005 *==========================================================================*/ 03006 03007 #define M1 1 03008 #define M3 3 03009 #define M4 4 03010 #define M3_STRING 14 03011 03012 typedef struct {int m1i1, m1i2, m1i3; char *m1p1, *m1p2, *m1p3;} mess_1; 03013 typedef struct {int m2i1, m2i2, m2i3; long m2l1, m2l2; char *m2p1;} mess_2; 03014 typedef struct {int m3i1, m3i2; char *m3p1; char m3ca1[M3_STRING];} mess_3; 03015 typedef struct {long m4l1, m4l2, m4l3, m4l4, m4l5;} mess_4; 03016 typedef struct {short m5c1, m5c2; int m5i1, m5i2; long m5l1, m5l2, m5l3;}mess_5; 03017 typedef struct {int m7i1, m7i2, m7i3, m7i4; char *m7p1, *m7p2;} mess_7; 03018 typedef struct {int m8i1, m8i2; char *m8p1, *m8p2, *m8p3, *m8p4;} mess_8; 03019 03020 typedef struct { 03021 int m_source; /* 消息的发送源 */ 03022 int m_type; /* 消息类型 what kind of message is it */ 03023 union { 03024 mess_1 m_m1; 03025 mess_2 m_m2;//消息内容有7种格式,如要发送消息包含3整数3指针时使用m_m1,传递3个int,2long,1指针时使用m_m2。 03026 mess_3 m_m3; 03027 mess_4 m_m4; 03028 mess_5 m_m5; 03029 mess_7 m_m7; 03030 mess_8 m_m8; 03031 } m_u; 03032 } message;//消息结构体 03033 03034 /* The following defines provide names for useful members. */ 03035 #define m1_i1 m_u.m_m1.m1i1 03036 #define m1_i2 m_u.m_m1.m1i2 03037 #define m1_i3 m_u.m_m1.m1i3 03038 #define m1_p1 m_u.m_m1.m1p1 03039 #define m1_p2 m_u.m_m1.m1p2 File: Page: 34 include/minix/ipc.h 03040 #define m1_p3 m_u.m_m1.m1p3 03041 03042 #define m2_i1 m_u.m_m2.m2i1 03043 #define m2_i2 m_u.m_m2.m2i2 03044 #define m2_i3 m_u.m_m2.m2i3 03045 #define m2_l1 m_u.m_m2.m2l1 03046 #define m2_l2 m_u.m_m2.m2l2 03047 #define m2_p1 m_u.m_m2.m2p1 03048 03049 #define m3_i1 m_u.m_m3.m3i1 03050 #define m3_i2 m_u.m_m3.m3i2 03051 #define m3_p1 m_u.m_m3.m3p1 03052 #define m3_ca1 m_u.m_m3.m3ca1 03053 03054 #define m4_l1 m_u.m_m4.m4l1 03055 #define m4_l2 m_u.m_m4.m4l2 03056 #define m4_l3 m_u.m_m4.m4l3 03057 #define m4_l4 m_u.m_m4.m4l4 03058 #define m4_l5 m_u.m_m4.m4l5 03059 03060 #define m5_c1 m_u.m_m5.m5c1 03061 #define m5_c2 m_u.m_m5.m5c2 03062 #define m5_i1 m_u.m_m5.m5i1 03063 #define m5_i2 m_u.m_m5.m5i2 03064 #define m5_l1 m_u.m_m5.m5l1 03065 #define m5_l2 m_u.m_m5.m5l2 03066 #define m5_l3 m_u.m_m5.m5l3 03067 03068 #define m7_i1 m_u.m_m7.m7i1 03069 #define m7_i2 m_u.m_m7.m7i2 03070 #define m7_i3 m_u.m_m7.m7i3 03071 #define m7_i4 m_u.m_m7.m7i4 03072 #define m7_p1 m_u.m_m7.m7p1 03073 #define m7_p2 m_u.m_m7.m7p2 03074 03075 #define m8_i1 m_u.m_m8.m8i1 03076 #define m8_i2 m_u.m_m8.m8i2 03077 #define m8_p1 m_u.m_m8.m8p1 03078 #define m8_p2 m_u.m_m8.m8p2 03079 #define m8_p3 m_u.m_m8.m8p3 03080 #define m8_p4 m_u.m_m8.m8p4 03081 03082 /*==========================================================================* 03083 * Minix run-time system (IPC). * 03084 *==========================================================================*/ 03085 03086 /* Hide names to avoid name space pollution. */ 03087 #define echo _echo 03088 #define notify _notify 03089 #define sendrec _sendrec 03090 #define receive _receive 03091 #define send _send 03092 #define nb_receive _nb_receive 03093 #define nb_send _nb_send 03094 //以下是消息传递的原语的原型 03095 _PROTOTYPE( int echo, (message *m_ptr) ); 03096 _PROTOTYPE( int notify, (int dest) ); 03097 _PROTOTYPE( int sendrec, (int src_dest, message *m_ptr) ); 03098 _PROTOTYPE( int receive, (int src, message *m_ptr) ); 03099 _PROTOTYPE( int send, (int dest, message *m_ptr) ); File: Page: 35 include/minix/ipc.h 03100 _PROTOTYPE( int nb_receive, (int src, message *m_ptr) ); 03101 _PROTOTYPE( int nb_send, (int dest, message *m_ptr) ); 03102 03103 #endif /* _IPC_H */
_PROTOTYPE,这个include/ansi.h中定义一个宏: #define_PROTOTYPE(function,params)function()
它允许使用如下形式写一个函数原型:
_PROTOTYPE(return-type function-name , (argument-type argument , ...) )
上面的消息原语中比较重要的是notify,sendrec,receive和send,非阻塞的nb_send和nb_receive调用大都被notify替换了。echo原型没有源和目的地址域,它对于生成代码没有任何帮助,但它可以检测发送和接收消息所用的时间。
进程间的高层通信代码在kernel/proc.c中。
3.2 进程的高层通信代码
在minix3中,进程间的通信使用的是消息传递,而系统调用也是通过消息传递的方式实现的!
源码下载地址: http://download.csdn.net/detail/hnust_xiehonghao/7701033
参考 http://www.cnblogs.com/zhangchaoyang/articles/1896607.html
http://blog.csdn.net/jianjun365222/article/details/4954916
http://www.cnblogs.com/zhangchaoyang
http://hi.baidu.com/swmonoku/item/c2de3df2a70767753d198b4e