如何调用系统调用?



所以我明白系统调用的用途和作用。 几乎任何需要计算机资源的东西都会在某个时候调用系统调用。我的问题是,例如,用户在Python中创建的程序如何编译并知道在哪里进行系统调用?如果我编写一个"Hello World"程序,编译器(在这种情况下为解释器(是否知道将 Python 中的 print(( 函数与其主机操作系统中的特定系统调用相关联?在用编程语言编写用户程序并将其转换为 1 和 0 的过程中,系统调用在哪里发挥作用?谢谢。

例如,

用户在Python中创建的程序如何编译并知道在哪里进行系统调用?

您可以自己探索其中的一些。

给定这个Python程序:print("Hello"),在UNIX系统上,人们可以猜测最终会调用write(2)系统调用。让我们看看这是否属实:

gdb -q --args python -c 'print("Hello")'
(gdb) catch syscall write
Catchpoint 1 (syscall 'write' [1])
(gdb) run
Starting program: /usr/bin/python -c print("Hello")
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Catchpoint 1 (call to syscall write), 0x00007ffff6f3cdd4 in __GI___libc_write (fd=1, buf=0x555555b2f9f0, nbytes=6) at ../sysdeps/unix/sysv/linux/write.c:26
26      ../sysdeps/unix/sysv/linux/write.c: No such file or directory.
(gdb) x/s $rsi
0x555555b2f9f0: "Hellon"
(gdb) bt
#0  0x00007ffff6f3cdd4 in __GI___libc_write (fd=1, buf=0x555555b2f9f0, nbytes=6) at ../sysdeps/unix/sysv/linux/write.c:26
#1  0x00007ffff6ecdb9d in _IO_new_file_write (f=0x7ffff720d760 <_IO_2_1_stdout_>, data=0x555555b2f9f0, n=6) at fileops.c:1183
#2  0x00007ffff6eccf3f in new_do_write (fp=0x7ffff720d760 <_IO_2_1_stdout_>, data=0x555555b2f9f0 "Hellon", to_do=to_do@entry=6) at libioP.h:839
#3  0x00007ffff6ecece9 in _IO_new_do_write (fp=<optimized out>, data=<optimized out>, to_do=6) at fileops.c:432
#4  0x00007ffff6ece26f in _IO_new_file_xsputn (f=0x7ffff720d760 <_IO_2_1_stdout_>, data=<optimized out>, n=1) at libioP.h:839
#5  0x00007ffff6ec2c3f in __GI__IO_fputs (str=0x55555580d74d "n", fp=0x7ffff720d760 <_IO_2_1_stdout_>) at libioP.h:839
#6  0x00005555556966ac in PyFile_WriteString ()
#7  0x000055555564c42d in PyEval_EvalFrameEx ()
#8  0x000055555564610a in PyEval_EvalCodeEx ()
#9  0x0000555555645a29 in PyEval_EvalCode ()
#10 0x0000555555676c5f in ?? ()
#11 0x00005555556a4846 in PyRun_StringFlags ()
#12 0x00005555556a567c in PyRun_SimpleStringFlags ()
#13 0x000055555562005a in Py_Main ()
#14 0x00007ffff6e7652b in __libc_start_main (main=0x55555561fb30 <main>, argc=3, argv=0x7fffffffdc78, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, 
stack_end=0x7fffffffdc68) at ../csu/libc-start.c:308
#15 0x000055555561fa4a in _start ()

你能从中推断出什么?

  1. 确实调用了write系统调用,$RSI寄存器中具有预期的字符(这恰好是系统调用的第二个参数必须用于此特定平台的位置(。
  2. 系统调用是从__GI___libc_write例程调用的,例程是libc提供的系统调用包装器
  3. Python没有直接调用__libc_write。它称为__GI__IO_fputs(实际上是fputs的别名。
  4. Python解释器print转换为对PyFile_WriteString的调用,该函数将实际工作委托给libc。

这并不罕见 - 事实上,大多数用户级程序并不直接执行系统调用。相反,它们调用libc例程,例如writefputs,并让 libc 担心如何在系统调用方面实现这些例程。

通过这样做,他们可以抽象出特定机器和操作系统的细节;他们希望在任何机器上找到一些libc,只有libc开发人员才需要担心实际的系统调用细节。

最新更新