CLONE_THREAD


cloneシステムコールをCLONE_THREADフラグによるpid/tid/sid/gidの検証サンプルです。
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/syscall.h>

#define STACK_SIZE (1024 * 1024)
void    get_pid(char *);

static int      childFunc(void *arg)
{
       get_pid("clone");
       return 0;
}

int     main(int argc, char *argv[])
{
    char *stack;
    char *stackTop;
    pid_t pid;

    stack = malloc(STACK_SIZE);
    stackTop = stack + STACK_SIZE;

    if(argc == 2) {
        get_pid("thread parent");
        pid = clone(childFunc, stackTop, CLONE_THREAD | CLONE_SIGHAND | CLONE_VM, NULL);
    }
    else {
        get_pid("parent");
        pid = clone(childFunc, stackTop, 0, NULL);
    }
    sleep(1);
    waitpid(pid, NULL, 0);
    exit(EXIT_SUCCESS);
}

void    get_pid(char* p)
{
    printf("%-20s: pid=%d, tid=%d, sid=%d gid=%d\n",
        p,
        syscall(SYS_getpid),
        syscall(SYS_gettid),
        syscall(SYS_getsid, 0),
        syscall(SYS_getpgid, 0));
}
SYS_getpid/SYS_gettid/SYS_getsid/SYS_getpgidシステムコールは以下の通りです。
pid=task->group_leader->pids[PIDTYPE_PID].pid
tid=task->pids[PIDTYPE_PID].pid
sid=task->group_leader->pids[PIDTYPE_SID].pid;
gid=task->group_leader->pids[PIDTYPE_PGID].pid;

結果

[root@localhost test]# ./a.out
parent              : pid=3415, tid=3415, sid=3222 gid=3415
clone               : pid=3416, tid=3416, sid=3222 gid=3415
CLONE_THREADでない時、クーロン作成時、 p->group_leader = pで、p->pids[PIDTYPE_PID]にプロセス自身のIDが、p->pids[PIDTYPE_PGID]にcurrent->pids[PIDTYPE_PGID]が、p->pids[PIDTYPE_SID]にcurrent->pids[PIDTYPE_SID]が設定されます。pidとtidはプロセス自身のI同で、sid/gidは親プロセスを継承します。CLONE_THREADならpidとtidは同値になります。

[root@localhost test]# ./a.out THREAD
thread parent       : pid=3425, tid=3425, sid=3222 gid=3425
clone               : pid=3425, tid=3426, sid=3222 gid=3425
CLONE_THREADの時、p->group_leader = current->group_leaderで、p->pids[PIDTYPE_PID]のみプロセス自身のIDが設定されます。従ってpid/tid/sid/gidは親のそれを継承します。pidとtidが異なるプロセスはCLONE_THREADである。と言う事です。pidが同じで、そのpidとtidプロセスが違うプロセス等は、pidのプロセスからCLONE_THREADで作成されたプロセスと言う事です。

補足

検証結果のparent/hread parentのgidは、pidと同じです。forkからcloneをコールすると、必ずgidは親のgidを継承しますが、シェルコマンドでのgidはカレントのpidと同じで、親(シェル)のgidを継承していません。

pidとgidが同じプロセスはグループリーダとなります。シェルがコマンドを起動する時、fork/cloneでプロセスを作成し、シェルがそのプロセスのgidをpidで更新して後、execで差し替えていると思います。(execが差し替えてるのかもしれません・・・)シェルで起動したコマンドプロセス毎に独自のpidをgidに設定することで、、以降の子プロセスはこのgidを継承することで、シェルコマンド下単位での管理が可能となります。

CLONE_THREADフラグは、 CLONE_SIGHANDが設定されてなければなりません。そしてCLONE_SIGHANDフラグは、CLONE_VMが設定されなければなりません。CLONE_THREADはCLONE_SIGHAND/CLONE_VMが設定されなければ、cloneはエラーとなります。

CLONE_SIGHANDはシグナル・ハン ドラを共有しますが、親プロセスのcurrent->sighand->countインクリメントするだけで、CLONE_VMはp->mm = current->mm/p->active_mm = current->mmとし、親プロセスのメモリ空間を共有します。故にCLONE_SIGHANDはcurrent->sighand->countインクリメントするだけでシグナルハンドラの共有が可能となり、CLONE_SIGHANDフラグは、CLONE_VMが設定されなければなりません。


最終更新 2015/06/15 13:51:55 - north
(2015/06/15 13:51:55 作成)


検索

アクセス数
3588617
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。