我正在尝试实现最小内核,并且正在尝试实现克隆系统调用。在手册页中,您可以看到克隆系统调用的定义如下:
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) 我正在研究在一个简单的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) 我对 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)。我首先希望这样做是为了提高代码的可读性以及自动完成功能。我猜想另一个解决方案是输入列表,如果可能的话,我也是好奇的。
谢谢你。
binary ×1
c ×1
glibc ×1
java ×1
java-threads ×1
jvm ×1
list ×1
python ×1
python-2.x ×1
python-3.x ×1
system-calls ×1