当前位置: 首页 > 知识库问答 >
问题:

为什么getpid被实现为系统调用?

范云
2023-03-14

我正在上我的第一堂操作系统课,所以希望我在这里没有任何大的误解。

我想知道为什么getpid()在Linux中实现为系统调用。据我所知,某些函数被做成系统调用,因为它们访问或更改操作系统可能想要保护的信息,所以它们被实现为系统调用,以便将控制权转移到内核。

但据我所知,getpid()只是返回调用进程的进程id。是否存在不授予此信息权限的情况?简单地让getpid()成为一个普通的用户函数不是很安全吗?

谢谢你的帮助。

共有3个答案

颛孙建业
2023-03-14

我认为将pid暴露给进程没有任何安全问题。操作系统强制执行进程地址空间隔离。如果我没记错的话,对getpid()的第一次调用是一个系统调用,但是以后对getpid()的调用会被缓存(可能由libc缓存)并在本地处理。

姬飞昂
2023-03-14

Getpid()可能只是从一个位置读取,但必须有人写入该位置。为了提供从写入垃圾到操作系统使用的位置的任何旧进程,需要保护它免受用户模式访问。为了让应用程序访问该位置,它需要在内核模式下这样做。因此,它必须作为系统调用完成。

闾丘玺
2023-03-14

在没有系统调用的情况下实现getpid()的唯一方法是首先执行一个系统调用并缓存其结果。然后,对getpid()的每次调用都将返回该缓存值,而无需系统调用。

但是,Linux手册页项目解释了为什么getpid()没有被缓存:

   From glibc version 2.3.4 up to and including version 2.24, the glibc
   wrapper function for getpid() cached PIDs, with the goal of avoiding
   additional system calls when a process calls getpid() repeatedly.
   Normally this caching was invisible, but its correct operation relied
   on support in the wrapper functions for fork(2), vfork(2), and
   clone(2): if an application bypassed the glibc wrappers for these
   system calls by using syscall(2), then a call to getpid() in the
   child would return the wrong value (to be precise: it would return
   the PID of the parent process).  In addition, there were cases where
   getpid() could return the wrong value even when invoking clone(2) via
   the glibc wrapper function.  (For a discussion of one such case, see
   BUGS in clone(2).)  Furthermore, the complexity of the caching code
   had been the source of a few bugs within glibc over the years.

   Because of the aforementioned problems, since glibc version 2.25, the
   PID cache is removed: calls to getpid() always invoke the actual
   system call, rather than returning a cached value.

总之,如果缓存了getpid(),它可能会返回错误的值(即使缓存在不允许任何程序写入的情况下完成得很好,等等)过去这是一个bug的来源。

通常,您在任何进程中只需要一个getpid()调用,如果您多次使用结果,请将其保存在变量中(应用程序级缓存!)。

干杯!

 类似资料:
  • 系统调用实现 系统调用的英文名字是System Call。操作系统为什么需要实现系统调用呢?其实这是实现了用户进程后,自然引申出来需要实现的操作系统功能。用户进程只能在操作系统给它圈定好的“用户环境”中执行,但“用户环境”限制了用户进程能够执行的指令,即用户进程只能执行一般的指令,无法执行特权指令。如果用户进程想执行一些需要特权指令的任务,比如通过网卡发网络包等,只能让操作系统来代劳了。于是就需要

  • 实现系统调用 目前,我们实现 sys_read sys_write 和 sys_exit 三个简单的系统调用。通过学习它们的实现,更多的系统调用也并没有多难。 用户程序中调用系统调用 在用户程序中实现系统调用比较容易,就像我们之前在操作系统中使用 sbi_call 一样,只需要符合规则传递参数即可。而且这一次我们甚至不需要参考任何标准,每个人都可以为自己的操作系统实现自己的标准。 例如,在实验指导

  • 我正在编写一个在Chrome中运行的HTML5应用程序,但它将在本地文件系统上运行(所以他们将通过双击html文件来启动它)。当我试图访问文件系统时,它会抛出一个错误,我想这是因为它是一个本地文件。有办法让Chrome允许这样做吗? 如果改为请求临时存储,它仍然会抛出一个错误,但现在是:

  • #include <stdio.h> int main(void) { char p1[] = "Sam"; char *p2 = "Bob"; printf("p1 is %s, p2 is %s\n", p1, p2); return 0; } 技巧 使用gdb调试程序时,可以使用catch syscall [name | number]为关注的系统调用设

  • 问题内容: 我正在尝试使用syscall 在Linux中分配一些内存。这是我尝试过的: 事情是按照linux调用约定,我希望返回值在寄存器中(指向已分配内存的指针)。我在gdb中运行了此文件,并在进行了syscall 后注意到以下寄存器内容 在系统调用之前 系统调用后 在这种情况下,我不太了解寄存器中的值。哪个指针可以用作我分配给它的8个字节的开头的指针? 问题答案: 系统调用返回值始终位于中。请

  • 问题内容: 关于的简单代码。是SessionScoped Bean,是RequestScoped Bean 内 我的问题是被叫很多。会告诉我们该方法在什么阶段被调用。首次加载页面时,请在阶段6-进行约 5次 呼叫。该页面上有一个,因此我在其中键入一些内容,然后单击(命令按钮)。然后在阶段1-> 4期间再呼叫 12次 。每个阶段调用此方法 3-4次 。然后,此属性的get 方法的setter方法(即