如何解决带有 futex 崩溃的 C 克隆地址处映射区域的权限错误
我正在尝试创建 64 个线程,我给每个线程 65536 个字节作为堆栈......但是从堆栈的顶部开始,我用 64 个字节来存储线程函数参数(前 4 个字节是线程 ID( 0 到 63),第二个 4 字节是线程消息长度(传递给 'write()
'),从字节 8 开始,它是由 sprintf
创建的线程消息(在线程创建之前(clone()
)))。在每个线程进程的顶部,我使用了:
syscall(SYS_futex,& __THREADS_STATUS[thread_id],FUTEX_WAIT,NULL,0);
让线程进入休眠状态,直到我们唤醒它:
syscall(SYS_futex,& __THREADS_STATUS[i],FUTEX_WAKE,1,0);
当一个线程醒来时,它使用lock方法锁定线程写进程然后写它的消息然后解锁被锁定的用户空间...
我们要唤醒15个线程来一个一个地写他们的消息(这就是为什么我用了locked!否则写的顺序不会被观察到)...
我预期的结果:
Thread #0 started
Thread #1 started
Thread #2 started
Thread #3 started
Thread #4 started
Thread #5 started
Thread #6 started
Thread #7 started
Thread #8 started
Thread #9 started
Thread #10 started
Thread #11 started
Thread #12 started
Thread #13 started
Thread #14 started
我得到了什么错误!!!!
Thread #0 started
Thread #2 started
Thread #12 started
Thread #11 started
==48072== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==48072== Bad permissions for mapped region at address 0x400BF0
==48072== at 0x400A8D: thread_main (in /tmp/tmp.x9XSQBiKue/cmake-build-release/threads_manager)
==48072== by 0x4F3EDC2: clone (in /usr/lib64/libc-2.28.so)
==48072== by 0x1200000001: ???
==48072== by 0x2320646165726853: ???
==48072== by 0x6574726174732031: ???
==48072== by 0xA63: ???
这是我的源代码(完整):
#define _GNU_SOURCE
#include <sched.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <syscall.h>
#include <sys/mman.h>
#include <linux/futex.h>
#include <stdatomic.h>
#define THREADS_COUNT 64
#define THREAD_STACK_SIZE 65536
#define THREAD_FLAGS (CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_PARENT|CLONE_THREAD|CLONE_IO)
static int thread_main(void * data);
static void thread_lock(int * user_space);
static void thread_unlock(int * user_space);
static int __THREADS_STATUS[THREADS_COUNT];
static int __THREADS_WRITE_LOCK = 1; /* 1 = available */
int
main() {
void * memory;
if((memory = mmap(0,(THREADS_COUNT * THREAD_STACK_SIZE),PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0)) == MAP_Failed) {
printf("mmap() Failed");
return 1;
}
for (int i = 0; i < THREADS_COUNT; i++) {
unsigned long long thread_stack_address = (unsigned long long) memory + THREAD_STACK_SIZE + (i * THREAD_STACK_SIZE) - 64;
/*
* At the end of each stack,we reserve 64 bytes to store:
* [0-4] => thread id
* [4-8] => thread message length to pass to 'write()'
* [8-n] => thread message to pass to 'write()'
*/
(*(int *)(thread_stack_address)) = i;
(*(int *)(thread_stack_address + 4)) = sprintf((char *)(thread_stack_address + 8),"Thread #%d started\n",i);
if(clone(thread_main,(void *) thread_stack_address,THREAD_FLAGS,(void *) thread_stack_address) == -1) {
printf("clone() Failed");
munmap(memory,(THREADS_COUNT * THREAD_STACK_SIZE));
return 1;
}
}
for (int i = 0; i < 15; i++) {
syscall(SYS_futex,0);
}
sleep(3);
munmap(memory,(THREADS_COUNT * THREAD_STACK_SIZE));
return 0;
}
static int
thread_main(void * data) {
int thread_id = (*(int *)(data));
int thread_msg_len = (*(int *)(data + 4));
char * thread_msg = (data + 8);
// Wait to woken up by the main process
syscall(SYS_futex,0);
// Lock to write then unlock ...
thread_lock(& __THREADS_WRITE_LOCK);
write(0,thread_msg,thread_msg_len);
thread_unlock(& __THREADS_WRITE_LOCK);
return 0;
}
static void
thread_lock(int * user_space) {
while (1) {
static const int one = 1;
if(atomic_compare_exchange_strong(user_space,& one,0))
break;
syscall(SYS_futex,user_space,0);
}
}
static void
thread_unlock(int * user_space) {
static const int zero = 0;
if(atomic_compare_exchange_strong(user_space,& zero,1)) {
syscall(SYS_futex,0);
}
}
似乎一切正常!!!但是因为这些:
thread_lock(& __THREADS_WRITE_LOCK);
write(0,thread_msg_len);
thread_unlock(& __THREADS_WRITE_LOCK);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。