linux clone线程,进程和线程创建glibc部分分析——clone() fork()

系统调用是操作系统提供的服务,用户程序通过各种系统调用,来引用内核提供的各种服务,系统调用的执行让

用户程序陷入内核,该陷入动作由swi软中断完成。当用户态的进程调用一个系统调用时,CPU通过软中断切换到

SVC模式并开始执行一个内核函数,完成用户态进程需要完成的工作。

fork():

path: glibc-2.3.6/nptl/sysdeps/unix/sysv/linux/pt-fork.c

#include // include __libc_fork()函数声明

pid_t __fork (void)

{

return __libc_fork ();

}

strong_alias (__fork, fork) // ./include/libc-symbols.h

// 实际上这里告诉编译器fork这个名字就代表着__fork这个名字,如果这里没有

// __fork()的定义,编译器就会报错。

// 类似地,存在weak_alias(XXX, xxx),也是取别名,但是编译器在XXX没有定义

// 的时候,不会报错。

// 可以参考强符号、弱符号,强引用和弱引用来理解它

vfork():

path: glibc-2.3.6/sysdeps/generic/vfork.c

#include

#include

__pid_t __vfork (void)

{

return __fork ();

}

libc_hidden_def (__vfork)

weak_alias (__vfork, vfork)

可以看出调用vfork是__vfork的别名,并且实际上是调用了__fork函数来实现__vfork函数的

clone():

path: glibc-2.3.6/sysdeps/unix/sysv/linux/arm/clone.S

该文件中是用汇编代码实现了__clone函数,存在:

weak_alias (__clone, clone)

__clone()函数声明如下:

extern int __clone (int (*__fn) (void *__arg), void *__child_stack,

int __flags, void *__arg, ...);

path: glibc-2.3.6/include/sched.h

pthread_create():

该函数的源码位置比较特殊,位于目录linuxthread目录下。

path:linuxthread/pthread.c

...

__pthread_create_2_1()

__pthread_create_2_0(),最终还是调用__pthread_create_2_1()来实现的。

*********************

__libc_fork():

path: glibc-2.3.6/nptl/sysdeps/unix/sysv/linux/fork.c

...

#ifdef ARCH_FORK

pid = ARCH_FORK ();

#else

# error "ARCH_FORK must be defined so that the CLONE_SETTID flag is

used"

pid = INLINE_SYSCALL (fork, 0);

#endif

...

这里pid = INLINE_SYSCALL (fork, 0);语句会得到执行,下面是3个重要的头文件:

sysdeps/unix/sysv/linux/arm/sysdep.h

sysdeps/unix/arm/sysdep.h

sysdeps/unix/sysdep.h

sysdeps/arm/sysdep.h

INLINE_SYSCALL这个宏定义于文件sysdeps/unix/sysv/linux/arm/sysdep.h中,该处的宏定义很复杂:

...

#define SYS_ify(syscall_name) (__NR_##syscall_name) // 获取中断号

//

中断号定义在:arm平台文件系统(制作文件系统时,需要拷贝交叉工具链中的头文件和库)中include/asm/unistd.h

#define __NR_restart_syscall (__NR_SYSCALL_BASE+ 0)

#define __NR_exit (__NR_SYSCALL_BASE+ 1)

#define __NR_fork (__NR_SYSCALL_BASE+ 2)

#define __NR_read (__NR_SYSCALL_BASE+ 3)

#define __NR_write (__NR_SYSCALL_BASE+ 4)

#define __NR_open (__NR_SYSCALL_BASE+ 5)

...

...

#define __NR_vfork (__NR_SYSCALL_BASE+ 190)

...

#define __NR_clone (__NR_SYSCALL_BASE+ 120)

...

...

***/

...

#undef INLINE_SYSCALL

#define INLINE_SYSCALL(name, nr, args...) \

({ unsigned int _sys_result = INTERNAL_SYSCALL (name, , nr, args);

\ // note1

if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result, ), 0))

\ // 软中断异常返回处理

{ \

__set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, )); \

_sys_result = (unsigned int) -1; \

} \

(int) _sys_result; })

#undef INTERNAL_SYSCALL_DECL

#define INTERNAL_SYSCALL_DECL(err) do { } while (0)

#undef INTERNAL_SYSCALL // note1

#define INTERNAL_SYSCALL(name, err, nr, args...) \

({ unsigned int _sys_result; \

{ \

register int _a1 asm ("a1"); \ // 定义一个寄存器变量,存放在a1 <==>

r0

LOAD_ARGS_##nr (args) \

asm volatile ("swi %1 @ syscall " #name \ // swi

产生一个软中断异常,%1代表第一个输入参数

: "=r" (_a1) \ // _a1 = rx

: "i" (SYS_ify(name)) ASM_ARGS_##nr \ // 输入参数:软中断号(立即数),参数列表

: "memory"); \ // 告诉编译器内存可能被改变

_sys_result = _a1; \

} \

(int) _sys_result; })

#undef INTERNAL_SYSCALL_ERROR_P

#define INTERNAL_SYSCALL_ERROR_P(val, err) \

((unsigned int) (val) >= 0xfffff001u)

#undef INTERNAL_SYSCALL_ERRNO

#define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))

#define LOAD_ARGS_0()

#define ASM_ARGS_0

#define LOAD_ARGS_1(a1) \

_a1 = (int) (a1); \

LOAD_ARGS_0 ()

#define ASM_ARGS_1 ASM_ARGS_0, "r" (_a1)

#define LOAD_ARGS_2(a1, a2) \

register int _a2 asm ("a2") = (int) (a2); \

LOAD_ARGS_1 (a1)

#define ASM_ARGS_2 ASM_ARGS_1, "r" (_a2)

#define LOAD_ARGS_3(a1, a2, a3) \

register int _a3 asm ("a3") = (int) (a3); \

LOAD_ARGS_2 (a1, a2)

#define ASM_ARGS_3 ASM_ARGS_2, "r" (_a3)

#define LOAD_ARGS_4(a1, a2, a3, a4) \

register int _a4 asm ("a4") = (int) (a4); \

LOAD_ARGS_3 (a1, a2, a3)

#define ASM_ARGS_4 ASM_ARGS_3, "r" (_a4)

#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \

register int _v1 asm ("v1") = (int) (a5); \

LOAD_ARGS_4 (a1, a2, a3, a4)

#define ASM_ARGS_5 ASM_ARGS_4, "r" (_v1)

#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \

register int _v2 asm ("v2") = (int) (a6); \

LOAD_ARGS_5 (a1, a2, a3, a4, a5)

#define ASM_ARGS_6 ASM_ARGS_5, "r" (_v2)

#define LOAD_ARGS_7(a1, a2, a3, a4, a5, a6, a7) \

register int _v3 asm ("v3") = (int) (a7); \

LOAD_ARGS_6 (a1, a2, a3, a4, a5, a6)

#define ASM_ARGS_7 ASM_ARGS_6, "r" (_v3)

APCS 是arm过程调用标准(ARM Procedure Call Standard)。

APCS 对我们通常称为 R0 到 R14 的寄存器起了不同的名字,如下:

Reg# APCS 意义

R0 a1 工作寄存器

R1 a2 "

R2 a3 "

R3 a4 "

R4 v1 必须保护

R5 v2 "

R6 v3 "

R7 v4 "

R8 v5 "

R9 v6 "

R10 sl 栈限制

R11 fp 桢指针

R12 ip

R13 sp 栈指针

R14 lr 连接寄存器

R15 pc 程序计数器

*********************

*********************

__clone()

.text

ENTRY(__clone)

@ sanity check args

cmp r0, #0

cmpne r1, #0

moveq r0, #-EINVAL

beq PLTJMP(syscall_error)

@ insert the args onto the new stack

str r3, [r1, #-4]! // 线程函数参数入栈,(child_stack)

str r0, [r1, #-4]! // 线程函数指针入栈

@ do the system call

@ get flags

mov r0, r2 // flags 存入r0

@ new sp is already in r1

swi SYS_ify(clone) // swi __NR_clone, 产生软中断异常

movs a1, a1

blt PLTJMP(C_SYMBOL_NAME(__syscall_error))

RETINSTR(ne, lr)

@ pick the function arg and call address off the stack and

execute

ldr r0, [sp, #4]

mov lr, pc

ldr pc, [sp]

@ and we are done, passing the return value through r0

b PLTJMP(_exit)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值