使用clone3创建新线程会导致段错误

问题描述 投票:0回答:1

我正在尝试使用 Linux clone3() 系统调用(在 Linux 5.3 中引入)来创建线程,而不使用标准库。虽然有很多使用旧的clone()系统调用的例子,但我还没有找到使用clone3()创建线程的明确例子。 我正在尝试做的事情:

直接使用clone3()系统调用创建线程 无需 libc (-nostdlib) 即可实现此功能 让线程执行一个打印消息的简单函数。

当前行为: 打印“Created”后,程序因 SIGSEGV 崩溃。 strace 输出显示:

execve("./clone3", ["./clone3"], 0x7ffc16f11ca0 /* 43 vars */) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN|MAP_STACK, -1, 0) = 0x7156c433d000
clone3({flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND, exit_signal=0, stack=0x7156c433d000, stack_size=0x2000}, 88) = 9973
write(1, "C", 1C)                        = 1
write(1, "r", 1r)                        = 1
write(1, "e", 1e)                        = 1
write(1, "a", 1a)                        = 1
write(1, "t", 1t)                        = 1
write(1, "e", 1e)                        = 1
write(1, "d", 1d)                        = 1
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x20040114d} ---
+++ killed by SIGSEGV (core dumped) +++
fish: Job 1, 'strace ./clone3' terminated by signal SIGSEGV (Address boundary error)

代码:

#define _GNU_SOURCE

#include <linux/mman.h>
#include <linux/sched.h>
#include <linux/time.h>
#include <stddef.h>
#include <sys/syscall.h>

typedef int (*thread_fn)(void *arg);

static inline long syscall6(long n, long a1, long a2, long a3, long a4, long a5,
                            long a6) {
  register long rax __asm__("rax") = n;
  register long rdi __asm__("rdi") = a1;
  register long rsi __asm__("rsi") = a2;
  register long rdx __asm__("rdx") = a3;
  register long r10 __asm__("r10") = a4;
  register long r8 __asm__("r8") = a5;
  register long r9 __asm__("r9") = a6;

  __asm__ volatile("syscall"
                   : "+r"(rax)
                   : "r"(rdi), "r"(rsi), "r"(rdx), "r"(r10), "r"(r8), "r"(r9)
                   : "rcx", "r11", "memory");
  return rax;
}
static inline long mmap(void *addr, size_t length, int prot, int flags, int fd,
                        long offset) {
  return syscall6(SYS_mmap, (long)addr, (long)length, (long)prot, (long)flags,
                  (long)fd, offset);
}
static inline void exit(int code) {
  syscall6(SYS_exit_group, code, 0, 0, 0, 0, 0);
}
static inline void sleep_seconds(unsigned int seconds) {
  struct timespec ts = {.tv_sec = seconds, .tv_nsec = 0};
  syscall6(SYS_nanosleep, (long)&ts, 0, 0, 0, 0, 0);
}
static inline void write_str(const char *str) {
  while (*str) {
    syscall6(SYS_write, 1, (long)str, 1, 0, 0, 0);
    str++;
  }
}
static inline long clone3(struct clone_args *args) {
  register long rax __asm__("rax") = SYS_clone3;
  register long rdi __asm__("rdi") = (long)args;
  register long rsi __asm__("rsi") = (long)sizeof(struct clone_args);
  __asm__ volatile("syscall"
                   : "+r"(rax)
                   : "r"(rdi), "r"(rsi)
                   : "r11", "memory");

  if (rax < 0) {
    write_str("clone3 was unsuccessful!");
    exit(1);
  }

  return rax;
}

int thread_func(void *arg) {
  write_str("Hello from thread!\n");
  sleep_seconds(1);
  return 0;
}

__attribute__((noreturn)) void _start() {
  const unsigned long STACK_SIZE = 8192;
  void *stack = (void *)mmap(
      0, STACK_SIZE, PROT_READ | PROT_WRITE,
      MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK | MAP_GROWSDOWN, -1, 0);

  void *stack_top = stack + STACK_SIZE;
  unsigned long *sp = (unsigned long *)stack_top;
  *(--sp) = 0;
  *(--sp) = (unsigned long)thread_func;

  struct clone_args args = {0};
  args.flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND;
  args.stack = (unsigned long)stack;
  args.stack_size = STACK_SIZE;

  long tid = clone3(&args);
  if (tid > 0) {
    write_str("Created thread!\n");
    sleep_seconds(2);
  }

  exit(0);
  __builtin_unreachable();
}

编译:

gcc clone3.c -static -nostdlib -fno-stack-protector -o clone3

Linux 内核:6.11.6

我已经查看了内核文档和手册页,但找不到使用clone3()创建线程的具体示例。任何有助于理解我所缺少的内容的帮助将不胜感激。

c linux multithreading system-calls
1个回答
0
投票

我从 Chris Wellons 那里找到了工作项目。阅读他的文章:https://nullprogram.com/blog/2023/03/23/ 和他的来源 我测试了编译器的源代码,这是一项工作。

© www.soinside.com 2019 - 2024. All rights reserved.