【问题标题】:Why bit shift left on system call bits?为什么在系统调用位上左移?
【发布时间】:2019-01-02 19:32:40
【问题描述】:

kernel/ipc.hTanenbaum 中将系统调用位定义为:

/* 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 &lt;&lt; RECEIVE 将是 0100 而不是 0010。这不是说时钟和系统任务可以通知但不能接收吗?

【问题讨论】:

  • ip.h 名称是位位置,表值是位掩码

标签: c kernel minix


【解决方案1】:

您从kernel/table.c 显示的代码中形成的值不是系统调用的代码编号的值。它们是系统调用的位掩码。

位掩码通常用于实现集合。假设我们有三个对象,例如一个苹果、一个香蕉和一个樱桃,我们希望记录某个集合 X 是否包含一个苹果、是否包含一个香蕉、是否包含一个樱桃。

我们可以通过分配位置 0 的位(值 1)来表示苹果,位置 1 的位(值 2)表示香蕉,以及位置 2 的位(值 4)来表示樱桃。那么任何集合 X 是否包含这些项目都可以用一个数字来表示,该数字是否具有相应的位集。例如,数字 5 在位置 0 和 2 处有位集合,因此它表示包含苹果和樱桃但不包含香蕉的集合。

kernel/table.c 中的代码分配位掩码中的位,以便使用代码 i 的系统调用由位置 i 处的位表示。因此,代码为 i 的系统调用的位掩码中位的值具有值1 &lt;&lt; i

下表显示了调用代码的值及其位掩码的值:

呼叫名称代码位掩码 发送 1 2 接收 2 4 发送记录 3 8 通知 4 16 回声 8 256

它们的使用方式是,为了表示包含多个调用的集合,将这些调用的位掩码值相加(或者,等效地,结合按位或运算)。所以包含SENDRECEIVESENDREC的集合用2+4+8 = 14表示。

所以1 &lt;&lt; SENDREC 是掩码中表示SENDREC 的位的值,1 &lt;&lt; ECHO 是表示掩码中ECHO 的位的值。这些值的 OR,1 &lt;&lt; SENDREC | 1 &lt;&lt; ECHO,是一个位掩码,包括SENDRECECHO,但不包括SEND 或其他代码。

对位掩码的一些操作是:

  • 如果i 是项目的编号,则1&lt;&lt;i 是在集合中表示它的位的值。
  • 使用X |= 1&lt;&lt;i 将一个项目i 添加到集合X,或将位添加到集合中。
  • 将两个集合 XY 合并,或将它们与 X | Y 合并。
  • 取两个集合XY的交集,将它们与X &amp; Y相加。

【讨论】:

  • 难道不是x &lt;&lt; i,其中x 是0 或1?
  • 哦!我想我明白了!你把1 &lt;&lt; i和它加上一些值,结果是x &lt;&lt; i,对吗?
  • @JakeKing:我添加了一些对位掩码进行简单操作的示例。
  • 等等,位掩码不能用value &amp; RECEIVE(value &amp; ECHO) | (value &amp; SENDREC)完成吗?
  • @JakeKing:value 是什么?如果它只是一个 0 或 1 表示开或关,那么,不,value &amp; RECEIVE 不是你想要的。 value &amp; RECEIVE 不会将该位移动到所需位置。尝试编写一些代码来移位和 AND 和 OR (并以十六进制或二进制显示结果)。