在kernel/ipc.h中,Tanenbaum将系统调用位定义为:
/* System call numbers that are passed when trapping to the kernel. The
* numbers are carefully defined so that it can easily be seen (based on
* the bits that are on) which checks should be done in sys_call().
*/
#define SEND 1 /* 0 0 0 1 : blocking send */
#define RECEIVE 2 /* 0 0 1 0 : blocking receive */
#define SENDREC 3 /* 0 0 1 1 : SEND + RECEIVE */
#define NOTIFY 4 /* 0 1 0 0 : nonblocking notify */
#define ECHO 8 /* 1 0 0 0 : echo a message */
但随后在kernel/table.c中,系统调用位定义为:
/* Define system call traps for the various process types. These call masks
* determine what system call traps a process is allowed to make.
*/
#define TSK_T (1 << RECEIVE) /* clock and system */
#define SRV_T (~0) /* system services */
#define USR_T ((1 << SENDREC) | (1 << ECHO)) /* user processes */
为什么所有内容都向左移? 1 << RECEIVE
会是 0100 而不是 0010 。这不是说时钟和系统任务可以通知但不能接收吗?
答案 0 :(得分:2)
您在kernel/table.c
中显示的代码中形成的值不是系统调用的代码号的值。它们是系统调用的位掩码。
位掩码通常用于实现集合。假设我们有三个对象,例如一个苹果,一个香蕉和一个樱桃,并且我们希望记录某些集合X是否包含一个苹果,不包含一个香蕉,是否包含一个香蕉。樱桃。
我们可以通过将位置0(值1)的位表示一个苹果,位置1(值2)的位表示一个香蕉,将位置2(值4)的位表示一个苹果来做到这一点。樱桃。然后,任何集合X是否包含这些项目都可以用一个数字来表示,该数字是否设置了相应的位。例如,数字5在位置0和2处有位,因此它表示一个包含苹果和樱桃但不包含香蕉的集。
kernel/table.c
中的代码在位掩码中分配位,以便代码 i 的系统调用由位置 i 处的位表示。因此,代码为 i 的系统调用的位掩码中的位的值为1 << i
。
这是一张表格,显示呼叫代码的值及其位掩码的值:
Call Name Code Number Bit Mask SEND 1 2 RECEIVE 2 4 SENDREC 3 8 NOTIFY 4 16 ECHO 8 256
使用这些方法的方式是,为了表示包含多个调用的集合,请将这些调用的位掩码值相加在一起(或等效地与按位或运算结合)。因此,包含SEND
,RECEIVE
和SENDREC
的集合由2 + 4 + 8 = 14表示。
因此1 << SENDREC
是掩码中代表SENDREC
的位的值,而1 << ECHO
是掩码中代表ECHO
的位的值。这些值1 << SENDREC | 1 << ECHO
的OR是一个位掩码,包含SENDREC
和ECHO
,但不包含SEND
或其他代码。
对位掩码的一些操作是:
i
是一项的编号,则1<<i
是表示集合中该项的位的值。i
添加到集合X
中,或使用X |= 1<<i
将位添加到集合中。X
和Y
这两个集合的并集,或与X | Y
进行或。X
和Y
的交集,并将它们与X & Y
相加。