小编dan*_*eld的帖子

当您调用克隆系统调用时,谁设置 RIP 寄存器?

我正在尝试实现最小内核,并且正在尝试实现克隆系统调用。在手册页中,您可以看到克隆系统调用的定义如下:

int clone(int (*fn)(void *), void *stack, int flags, void *arg, ...
                 /* pid_t *parent_tid, void *tls, pid_t *child_tid */ );
Run Code Online (Sandbox Code Playgroud)

如您所见,它接收一个函数指针。如果您更仔细地阅读手册页,您实际上可以看到内核中的实际系统调用实现不接收函数指针:

long clone(unsigned long flags, void *stack,
                      int *parent_tid, int *child_tid,
                      unsigned long tls);
Run Code Online (Sandbox Code Playgroud)

那么,我的问题是,创建线程后谁修改RIP寄存器?是libc吗?

我在 glibc 中找到了这段代码:https://elixir.bootlin.com/glibc/latest/source/sysdeps/unix/sysv/linux/x86_64/clone.S但我不确定该函数实际上在什么时候被调用。

额外的信息:

查看clone.S源代码时,您可以看到它在系统调用之后跳转到thread_start分支。在克隆系统调用之后的分支上(因此只有子进程执行此操作),它会从堆栈中弹出函数地址和参数。谁实际将这些参数和函数地址压入堆栈?我猜它必须发生在内核中的某个地方,因为在指令点syscall它们不在那里。

这是一些 gdb 输出:

在系统调用之前:

[-------------------------------------code-------------------------------------]
   0x7ffff7d8af22 <clone+34>:   mov    r8,r9
   0x7ffff7d8af25 <clone+37>:   mov    r10,QWORD PTR [rsp+0x8]
   0x7ffff7d8af2a <clone+42>:   mov    eax,0x38
=> 0x7ffff7d8af2f <clone+47>:   syscall 
   0x7ffff7d8af31 <clone+49>:   test   rax,rax
   0x7ffff7d8af34 <clone+52>:   jl     0x7ffff7d8af49 <clone+73>
   0x7ffff7d8af36 <clone+54>:   je …
Run Code Online (Sandbox Code Playgroud)

c binary operating-system glibc system-calls

5
推荐指数
1
解决办法
943
查看次数

System.out.println 在线程级别是如何工作的?

我正在研究在一个简单的HelloWorldjava 程序上进行了哪些系统调用。通过一个简单的strace我注意到没有write电话,我发现这是可疑的:

...
mprotect(0x7f0bcd852000, 4096, PROT_READ) = 0
mprotect(0x7f0bce915000, 790528, PROT_READ) = 0
getpid()                                = 27931
munmap(0x7f0bcf6ac000, 174284)          = 0
getpid()                                = 27931
mmap(NULL, 1052672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7f0bcf5d6000
clone(child_stack=0x7f0bcf6d5fb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f0bcf6d69d0, tls=0x7f0bcf6d6700, child_tidptr=0x7f0bcf6d69d0) = 27932
futex(0x7f0bcf6d69d0, FUTEX_WAIT, 27932, NULLHello, World
) = 0
munmap(0x7f0bbfa6c000, 140063364)       = 0
close(3)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
Run Code Online (Sandbox Code Playgroud)

因此,正如您在上面看到的,在正常strace调用中,只会进行一次futex调用,该调用正在等待字符串地址。

因此,我strace使用-f参数运行以查看所有线程:

[pid 28249] pread64(3, …
Run Code Online (Sandbox Code Playgroud)

java multithreading jvm java-threads

2
推荐指数
1
解决办法
91
查看次数

如何为 Python 变量显式指定类类型?

我对 Python 相当陌生,来自 Java 背景。我有这样的事情:

class A:
    def __init__(self):
        self.var1 = 1
        self.var2 = 2

class B:
    def __init__(self):
        self.my_list = []

    def add(self, a_object):
        self.my_list.append(a_object)

    def show(self):
        for a_object in self.my_list:
            print(a_object.var1, a_object.var2)
Run Code Online (Sandbox Code Playgroud)

现在,我知道这段代码会运行,但我的问题是,是否有任何方法可以在show方法中指定该a_object变量实际上是类型 A 的对象(例如类型转换 - 我会在 java 中编写类似的东西(A)a_object)。我首先希望这样做是为了提高代码的可读性以及自动完成功能。我猜想另一个解决方案是输入列表,如果可能的话,我也是好奇的。

谢谢你。

python list python-2.x python-3.x python-typing

0
推荐指数
1
解决办法
45
查看次数