系统调用clone()函数

    类似于fork()和vfork(),Linux特有的系统调用clone()也能创建一个新线程。与前两者不同的是,后者在进程创建期间对步骤的控制更为准确。其主要用于线程库的实现。其函数原型如下:

#define _GNU_SOURCE
#include <sched.h>
int clone(int (*func)(void*),void *child_stack,int flags,void *func_arg,....
           /*pid_t *ptid,struct user_desc *tls,pid_t *ctid*/);
                  
                                     Return process ID of child on success,or -1 on error

     如同fork(),由clone()创建的新进程几近于父进程的翻版。

     但是与fork()不同的是,克隆生成的子进程继续运行时不以调用处为起点,转而去调用以参数func所指定的函数,func又称为子函数。调用子函数时的参数由func_arg指定。经过转换,子函数可对改参数的含义自由解读,例如可以作为整型值(int),也可以视为指向结构的指针。

    当函数func返回或者是调用exit()(或者_exit())之后,克隆产生的子进程就会终止。照例,父进程可以通过wait()一类函数来等待克隆子进程。

因为克隆产生的子进程可能共享父进程内存,所以它不能使用父进程的栈。相反,调用者必须分配一块大小适中的内存空间供子进程的栈使用,同时将这块内存的指针置于参数child_stack中。

    参数flags服务于双重目的。首先,其低字节中存放着子进程的终止信号,子进程退出时其父进程将收到这一信号。(如果克隆产生的子进程因信号而终止,父进程依然会收到SIGCHLD信号)该字节也可能为0,这时将不会产生任何信号。

clone()函数中的flags参数是各位掩码的组合。其参数如下:

  • 共享文件描述符:CLONE_FILES

如果指定了该标志,父子进程会共享同一个打开文件描述符表。也就是说,无论哪个进程对文件描述符的分配与释放都会影响宁一个进程。

  • 共享与文件系统相关的信息:CLONE_FS

如果指定了该标志,那么父子进程将共享与文件系统相关的信息:权限掩码、根目录以及当前工作目录。也就是说无论在哪个进程中调用umask()、chdir()或者chroot(),都将影响到另一个进程。

  • 共享对信号的处置设置:CLONE_SIGHAND

如果设置了该标志,那么父子进程将共享同一信号处置表。无论在哪个进程中调用sigaction()或者signal()来改变对信号处置的设置,都会影响其他进程对信号的处置。

  • 共享父进程的虚拟内存:CLONE_VM

如果设置了该标志,父子进程将会共享同一份虚拟内存页。无论哪一个进程更新了内存,或是调用了mmap()、munmap(),另一进程同样会观察到变化。

  • 线程组:CLONE_THREAD

若设置了该标志,则会将子进程置于父进程的线程组中。如果未设置该标志,那么会将子进程置于新的线程组中。

  • 线程库支持:CLONE_PARENT_SETTID、CLONE_CHILD_SETTID和CLONE_CHILD_CLEARTID

为实现POSIX线程,Linux2.6提供了对CLONE_PARENT_SETTID、CLONE_CHILD_SETTID和CLONE_CHILD_CLEARTID的支持。这些标志将会影响clone()对参数ptid、ctid的处理。如果设置了CLONE_PARENT_SETTID,内核会将子进程的线程ID写入ptid所指向的位置。如果设置了CLONE_CHILD_SETTID,那么clone()会将子线程的线程ID写入指针ctid所指向的位置。如果设置了CLONE_CHILD_CLEARTID,则会在子进程终止时将ctid所指向的内存清零。

  • 线程本地存储:CLONE_SETTLS

如果设置了该标志,那么参数tls所指向的user_desc结构会对线程所使用的线程本地存储缓冲区加以描述。

  • 共享systemV信号量的撤销值:CLONE_SYSVSEM

如果设置了该标志,父子进程会将共享同一个SystemV信号量撤销值列表。

  • 每进程挂载命名空间:CLONE_NEWNS
  • 将子进程的父进程置为调用者的父进程:CLONE_PARENT

默认情况下,当调用clone()创建新进程时,新进程的父进程就用clone()进程。如果设置该标志,那么调用者的父进程就成为子进程的父进程。

  • 进程跟踪:CLONE_PTRACE和CLONE_UNTRACED

如果设置了CLONE_PTRACE且正在跟踪子进程,那么也会对子进程进行跟踪。从Linux2.6起,即可设置CLONE_UNTRACED标志,这也意味着跟踪进程不能强制其子进程设置为CLONE_PTRACE

  • 挂起父进程直至子进程退出或者调用exec():CLONE_VFORK

如果设置了该标识,父进程将一直挂起,直至子进程调用exec()或者_exit()来释放虚拟内存资源为止。

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`clone` 是 Linux 系统提供的一个系统调用,用于创建一个新的进程,该进程与父进程共享一些资源,但也可以拥有自己独立的资源。 `clone` 系统调用函数原型如下: ```c #include <sched.h> int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ... /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ ); ``` 其中,参数含义如下: - `fn`:新进程的入口函数,该函数会在新进程中被调用执行。 - `child_stack`:指向新进程的栈空间,用于存储新进程的栈数据。栈是从高地址向低地址生长的,因此 `child_stack` 指向的地址应该是栈空间的最高地址,也就是栈顶。 - `flags`:创建新进程的标志,它是一个位掩码,可以包含以下标志位: - `CLONE_VM`:新进程与父进程共享内存空间。 - `CLONE_FS`:新进程与父进程共享文件系统信息。 - `CLONE_FILES`:新进程与父进程共享打开的文件描述符。 - `CLONE_SIGHAND`:新进程与父进程共享信号处理函数。 - `CLONE_THREAD`:新进程被视为调用进程的一个线程,与父进程共享进程 ID 和资源。 - `arg`:传递给新进程入口函数的参数,可以是任何类型的数据。 - `ptid`:如果不为 `NULL`,则返回子进程的线程 ID。 - `tls`:如果不为 `NULL`,则指向一个用户描述符,用于设置新进程的线程本地存储 (TLS)。 - `ctid`:如果不为 `NULL`,则返回子进程的 PID。 `clone` 系统调用创建的新进程可以在一个新的命名空间中运行,因此可以提供一定程度的隔离性。同时,由于新进程与父进程共享一些资源,因此可以实现一些特殊的进程管理技术,例如线程和进程的混合调度等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值