Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C QEMU用户模式仿真是否以防止pthread_join阻塞的方式退出?_C_Multithreading_Pthreads_Qemu_System Calls - Fatal编程技术网

C QEMU用户模式仿真是否以防止pthread_join阻塞的方式退出?

C QEMU用户模式仿真是否以防止pthread_join阻塞的方式退出?,c,multithreading,pthreads,qemu,system-calls,C,Multithreading,Pthreads,Qemu,System Calls,我正在尝试将QEMU的用户模式模拟器作为一个线程运行在我正在编写的更大程序中。我修改了linux user/main.c文件,使标准的int main(int-argc,char**argv,char**envp函数现在被称为void*qemu\u user\u mode\u func(void*arg)。我还将pthread\u exit(NULL)添加到该函数的末尾,这是pthreads的标准做法(或者我已经被告知) 但是,当我尝试运行包含我自己的测试函数的第二个线程时(如下面的void*t

我正在尝试将QEMU的用户模式模拟器作为一个线程运行在我正在编写的更大程序中。我修改了
linux user/main.c
文件,使标准的
int main(int-argc,char**argv,char**envp
函数现在被称为
void*qemu\u user\u mode\u func(void*arg)
。我还将
pthread\u exit(NULL)
添加到该函数的末尾,这是pthreads的标准做法(或者我已经被告知)

但是,当我尝试运行包含我自己的测试函数的第二个线程时(如下面的
void*test\u func(void*arg)
中所示),即使调用
pthread\u join(
tid
),进程也会在第二个线程完成之前退出
,我已经读过它,它会阻止调用线程,直到线程
tid
返回。QEMU的用户模式模拟退出时是否会阻止
pthread\u join
退出,或者我只是使用了错误的线程

这是我的代码(不包括大部分的
qemu\u user\u mode\u func
):

void*qemu\u user\u mode\u func(void*arg)
{
线程数据*线程数据;
int-argc;
字符**argv;
炭**envp;
/**QEMU标准码**/
//返回0;
pthread_exit(NULL);
}
void*test_func(void*arg){
结构时间段时间;
time.tv_sec=7;
time.tv_nsec=0;
纳秒睡眠(&时间,空);
printf(“你好,世界-来自线程\n”);
pthread_exit(NULL);
}
内部主(内部argc、字符**argv、字符**envp){
//初始化变量以创建线程
int rc;
pthread_t线程[2];
线程数据主参数;
main_args.tid=1;
main_args.argc=argc;
main_args.argv=argv;
main_args.envp=envp;
//创建线程
if((rc=pthread_create(&(threads[0]),NULL,test_func,NULL))){
fprintf(stderr,“错误:pthread_create,rc:%d\n”,rc);
返回退出失败;
}
if((rc=pthread_create(&(threads[1]),NULL,qemu_user_mode_func,(void*)和main_args))){
fprintf(stderr,“错误:pthread_create,rc:%d\n”,rc);
返回退出失败;
}
//等待线程完成,然后终止进程
对于(rc=0;rc<2;rc++){
pthread_join(线程[rc],NULL);
}
返回0;
}

编辑:我在
无效cpu_循环(CPUX86State*env)
函数中发现,当仿真程序得出结论时,QEMU调用syscall 231,这是
系统退出_组
(根据)。因此,我猜这个系统调用将终止我正在运行的整个进程。我希望您能提供一些有关如何绕过这个问题的提示!

如果您将一个复杂的预先存在的应用程序转换为线程,将会出现一些问题。其中之一是,应用程序可以调用
exit
或其变体,从而终止整个程序。Th有许多其他问题可能会导致问题。我建议使用。

如果您将一个复杂的现有应用程序转换为线程,则会出现一些问题。其中一个问题是,应用程序可以调用
exit
或其变体,从而终止您的整个程序。还有许多其他问题可以解决使用问题。我建议使用。

问题通过编辑
无效cpu\u循环(CPUX86State*env)
中的以下部分得到解决。在执行系统调用之前,我捕获
sys\u exit\u group
sys\u exit
系统调用,然后从函数返回

原件:

void cpu_loop(CPUX86State *env)
{
    CPUState *cs = CPU(x86_env_get_cpu(env));
    int trapnr;
    abi_ulong pc;
    target_siginfo_t info;

    for(;;) {
        cpu_exec_start(cs);
        trapnr = cpu_x86_exec(env);
        cpu_exec_end(cs);
        switch(trapnr) {
        case 0x80:
            /* linux syscall from int $0x80 */
            env->regs[R_EAX] = do_syscall(env,
                                          env->regs[R_EAX],
                                          env->regs[R_EBX],
                                          env->regs[R_ECX],
                                          env->regs[R_EDX],
                                          env->regs[R_ESI],
                                          env->regs[R_EDI],
                                          env->regs[R_EBP],
                                          0, 0);
            break;
#ifndef TARGET_ABI32
        case EXCP_SYSCALL:
            /* linux syscall from syscall instruction */
            env->regs[R_EAX] = do_syscall(env,
                                          env->regs[R_EAX],
                                          env->regs[R_EDI],
                                          env->regs[R_ESI],
                                          env->regs[R_EDX],
                                          env->regs[10],
                                          env->regs[8],
                                          env->regs[9],
                                          0, 0);
            break;
#endif
修改:

void cpu_loop(CPUX86State *env)
{
    CPUState *cs = CPU(x86_env_get_cpu(env));
    int trapnr;
    abi_ulong pc;
    target_siginfo_t info;

    for(;;) {
        cpu_exec_start(cs);
        trapnr = cpu_x86_exec(env);
        cpu_exec_end(cs);
        switch(trapnr) {
        case 0x80:
            /* linux syscall from int $0x80 */
            env->regs[R_EAX] = do_syscall(env,
                                          env->regs[R_EAX],
                                          env->regs[R_EBX],
                                          env->regs[R_ECX],
                                          env->regs[R_EDX],
                                          env->regs[R_ESI],
                                          env->regs[R_EDI],
                                          env->regs[R_EBP],
                                          0, 0);
            break;
#ifndef TARGET_ABI32
        case EXCP_SYSCALL:
            /* linux syscall from syscall instruction */
----> if ((env->regs[R_EAX] == __NR_exit_group) || (env->regs[R_EAX] == __NR_exit)) {
                return; 
            }
            env->regs[R_EAX] = do_syscall(env,
                                          env->regs[R_EAX],
                                          env->regs[R_EDI],
                                          env->regs[R_ESI],
                                          env->regs[R_EDX],
                                          env->regs[10],
                                          env->regs[8],
                                          env->regs[9],
                                          0, 0);
            break;
#endif

通过编辑
void cpu\u loop(CPUX86State*env)
中的以下部分,问题得以解决。我在执行系统调用之前捕获了
sys\u exit\u group
sys\u exit
系统调用,而只是从函数返回

原件:

void cpu_loop(CPUX86State *env)
{
    CPUState *cs = CPU(x86_env_get_cpu(env));
    int trapnr;
    abi_ulong pc;
    target_siginfo_t info;

    for(;;) {
        cpu_exec_start(cs);
        trapnr = cpu_x86_exec(env);
        cpu_exec_end(cs);
        switch(trapnr) {
        case 0x80:
            /* linux syscall from int $0x80 */
            env->regs[R_EAX] = do_syscall(env,
                                          env->regs[R_EAX],
                                          env->regs[R_EBX],
                                          env->regs[R_ECX],
                                          env->regs[R_EDX],
                                          env->regs[R_ESI],
                                          env->regs[R_EDI],
                                          env->regs[R_EBP],
                                          0, 0);
            break;
#ifndef TARGET_ABI32
        case EXCP_SYSCALL:
            /* linux syscall from syscall instruction */
            env->regs[R_EAX] = do_syscall(env,
                                          env->regs[R_EAX],
                                          env->regs[R_EDI],
                                          env->regs[R_ESI],
                                          env->regs[R_EDX],
                                          env->regs[10],
                                          env->regs[8],
                                          env->regs[9],
                                          0, 0);
            break;
#endif
修改:

void cpu_loop(CPUX86State *env)
{
    CPUState *cs = CPU(x86_env_get_cpu(env));
    int trapnr;
    abi_ulong pc;
    target_siginfo_t info;

    for(;;) {
        cpu_exec_start(cs);
        trapnr = cpu_x86_exec(env);
        cpu_exec_end(cs);
        switch(trapnr) {
        case 0x80:
            /* linux syscall from int $0x80 */
            env->regs[R_EAX] = do_syscall(env,
                                          env->regs[R_EAX],
                                          env->regs[R_EBX],
                                          env->regs[R_ECX],
                                          env->regs[R_EDX],
                                          env->regs[R_ESI],
                                          env->regs[R_EDI],
                                          env->regs[R_EBP],
                                          0, 0);
            break;
#ifndef TARGET_ABI32
        case EXCP_SYSCALL:
            /* linux syscall from syscall instruction */
----> if ((env->regs[R_EAX] == __NR_exit_group) || (env->regs[R_EAX] == __NR_exit)) {
                return; 
            }
            env->regs[R_EAX] = do_syscall(env,
                                          env->regs[R_EAX],
                                          env->regs[R_EDI],
                                          env->regs[R_ESI],
                                          env->regs[R_EDX],
                                          env->regs[10],
                                          env->regs[8],
                                          env->regs[9],
                                          0, 0);
            break;
#endif

我非常清楚这一点——不幸的是,没有其他虚拟化程序执行(1)动态二进制转换,并且(2)具有AARCH64支持(我知道)。幸运的是,这有一个简单(尽管很难看)的修复。我非常清楚这一点——不幸的是,没有其他虚拟化程序执行(1)动态二进制翻译,并且(2)支持AARCH64(我知道)。幸运的是,它有一个简单的(尽管很难看)修复。你能解释一下你所做的改变,以便其他人将来能从中受益吗?@SevenBits是的-刚刚编辑了解决方案。也切换到了原来的标题-它认为它更好地抓住了问题的本质。谢谢你的建议!你能解释一下你所做的改变,以便其他人将来能从中受益吗?@SevenBits是的-刚刚编辑了解决方案。也切换到了原始标题-它认为它更好地抓住了问题的本质。谢谢你的建议!你为什么不干脆
fork()
并在forked child中调用qemu main函数?@caf-这与我如何使用qemu有关-主要是,我正在利用其中的动态二进制翻译系统,称为微型代码生成器。我试图在程序执行的一部分开始使用DBT-例如,程序从本机硬件启动,然后迁移到虚拟机执行的一部分。由于二进制文件的文本+数据部分在线程之间共享,因此对这些部分的任何内存引用在两个线程中都是有效的;所有更改都是堆栈(这是另一个野兽)。我同意
fork
通常是更好的解决方案!为什么不干脆
fork()
并在forked child中调用qemu main函数?@caf-这与我如何使用qemu有关-主要是,我正在利用其中的动态二进制翻译系统,称为微型代码生成器。我试图在程序执行的一部分开始使用DBT-例如,程序从本机硬件启动,然后迁移到虚拟机执行的一部分。由于