ucontext.h和uc_link不从主线程返回

时间:2016-01-27 20:56:24

标签: c

这是我想要做的更大的线程调度api的一部分。

我想创建一个线程,当主线程(创建线程的线程)退出时,我刚刚创建的线程应该执行。我试图用ucontext和uc_link来做这个,但它不起作用。当我尝试为当前线程设置它时,我的uc_link似乎不起作用。

以下是此链接中稍微修改过的示例,这是我厌倦了这项工作。

http://pubs.opengroup.org/onlinepubs/009695399/functions/makecontext.html

#include <stdio.h>
#include <ucontext.h>


static ucontext_t ctx[3];


static void
f1 (void)
{
    puts("start f1");
    swapcontext(&ctx[1], &ctx[2]);
    puts("finish f1");
}


static void
f2 (void)
{
    puts("start f2");
    swapcontext(&ctx[2], &ctx[1]);
    puts("finish f2");
}


int
main (void)
{
    char st1[8192];
    char st2[8192];


    getcontext(&ctx[1]);
    ctx[1].uc_stack.ss_sp = st1;
    ctx[1].uc_stack.ss_size = sizeof st1;
    ctx[1].uc_link = 0;
    makecontext(&ctx[1], f1, 0);


    getcontext(&ctx[2]);
    ctx[2].uc_stack.ss_sp = st2;
    ctx[2].uc_stack.ss_size = sizeof st2;
    ctx[2].uc_link = &ctx[1];
    makecontext(&ctx[2], f2, 0);

    getcontext(&ctx[0]);
    ctx[0].uc_link = &ctx[2];
    return 0;
}

预期产出:

finished main
start f2
start f1
finish f2
finish f1

给定输出:

finished main

如何以有意义的方式为当前线程/进程设置uc_link?

2 个答案:

答案 0 :(得分:0)

使用以下代码替换上面代码中的main会产生预期的输出。

This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.

It was created by libgpg-error configure 1.20, which was
generated by GNU Autoconf 2.69.  Invocation command line was

$ ./configure --disable-shared --enable-static --with-pic --enable-threads=posix --host i386-apple-darwin --with-sysroot=/Applications/Xcode 3.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator9.1.sdk --prefix=/Users/jayaraj/Desktop/ChatSecure-iOS/Submodules/OTRKit/scripts/build/iPhoneSimulator-9.1-i386 LDFLAGS=-L/Users/jayaraj/Desktop/ChatSecure-iOS/Submodules/OTRKit/scripts/built/i386/lib -fPIE -miphoneos-version-min=8.0 CFLAGS= -arch i386 -fPIE -isysroot /Applications/Xcode     3.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator9.1.sdk -I/Users/jayaraj/Desktop/ChatSecure-iOS/Submodules/OTRKit/scripts/built/i386/include -miphoneos-version-min=8.0 CPPLAGS= -arch i386 -fPIE -isysroot /Applications/Xcode 3.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator9.1.sdk -I/Users/jayaraj/Desktop/ChatSecure-iOS/Submodules/OTRKit/scripts/built/i386/include -miphoneos-version-min=8.0

## --------- ##
## Platform. ##
## --------- ##

hostname = Irudayarajs-iMac.local
uname -m = x86_64
uname -r = 15.0.0
uname -s = Darwin
uname -v = Darwin Kernel Version 15.0.0: Wed Aug 26 16:57:32 PDT 2015;     root:xnu-3247.1.106~1/RELEASE_X86_64

/usr/bin/uname -p = i386
/bin/uname -X     = unknown

/bin/arch              = unknown
/usr/bin/arch -k       = unknown
/usr/convex/getsysinfo = unknown
/usr/bin/hostinfo      = Mach kernel version:
     Darwin Kernel Version 15.0.0: Wed Aug 26 16:57:32 PDT 2015; root:xnu-    3247.1.106~1/RELEASE_X86_64
Kernel configured for up to 4 processors.
4 processors are physically available.
4 processors are logically available.
Processor type: x86_64h (Intel x86-64h Haswell)
Processors active: 0 1 2 3
Primary memory available: 8.00 gigabytes
Default processor set: 251 tasks, 1124 threads, 4 processors
Load average: 1.54, Mach factor: 2.44
/bin/machine           = unknown
/usr/bin/oslevel       = unknown
/bin/universe          = unknown

PATH: /usr/local/bin
PATH: /usr/bin
PATH: /bin
PATH: /usr/sbin
PATH: /sbin
PATH: /opt/X11/bin
PATH: /usr/local/MacGPG2/bin


## ----------- ##
## Core tests. ##
## ----------- ##

configure:2647: checking for a BSD-compatible install
configure:2715: result: /usr/local/bin/ginstall -c
configure:2726: checking whether build environment is sane
configure:2781: result: yes
configure:2840: checking for i386-apple-darwin-strip
configure:2870: result: no
configure:2880: checking for strip
configure:2896: found /usr/bin/strip
configure:2907: result: strip
configure:2932: checking for a thread-safe mkdir -p
configure:2971: result: /usr/local/bin/gmkdir -p
configure:2978: checking for gawk
configure:3008: result: no
configure:2978: checking for mawk
configure:3008: result: no
configure:2978: checking for nawk
configure:3008: result: no
configure:2978: checking for awk
configure:2994: found /usr/bin/awk
configure:3005: result: awk
configure:3016: checking whether make sets $(MAKE)
configure:3038: result: yes
configure:3067: checking whether make supports nested variables
configure:3084: result: yes
configure:3211: checking whether to enable maintainer-specific portions of     Makefiles
configure:3220: result: no
configure:3248: checking whether make supports nested variables
configure:3265: result: yes
configure:3283: checking build system type
configure:3297: result: x86_64-apple-darwin15.0.0
configure:3317: checking host system type
configure:3330: result: i386-apple-darwin
configure:3354: autobuild project... libgpg-error
configure:3356: autobuild revision... 1.20
configure:3360: autobuild hostname... Irudayarajs-iMac.local
configure:3369: autobuild timestamp... 20160128-095704
configure:3383: checking for i386-apple-darwin-gcc
configure:3410: result: gcc
configure:3679: checking for C compiler version
configure:3688: gcc --version >&5
Apple LLVM version 7.0.0 (clang-700.1.76)
Target: x86_64-apple-darwin15.0.0
Thread model: posix
Configured with: --prefix=/Applications/Xcode 3.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
configure:3699: $? = 0
configure:3688: gcc -v >&5
Configured with: --prefix=/Applications/Xcode 3.app/Contents/Developer/usr --    with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.0 (clang-700.1.76)
Target: x86_64-apple-darwin15.0.0
Thread model: posix
configure:3699: $? = 0
configure:3688: gcc -V >&5
clang: error: argument to '-V' is missing (expected 1 value)
clang: error: no input files
configure:3699: $? = 1
configure:3688: gcc -qversion >&5
clang: error: unknown argument: '-qversion'
clang: error: no input files
configure:3699: $? = 1
configure:3719: checking whether the C compiler works
configure:3741: gcc  -arch i386 -fPIE -isysroot /Applications/Xcode     3.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator9.1.sdk -I/Users/jayaraj/Desktop/ChatSecure-iOS/Submodules/OTRKit/scripts/built/i386/include -miphoneos-version-min=8.0  -L/Users/jayaraj/Desktop/ChatSecure-iOS/Submodules/OTRKit/scripts/built/i386/lib -fPIE -miphoneos-version-min=8.0 conftest.c  >&5
clang: error: no such file or directory:     '3.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPho    neSimulator9.1.sdk'
clang: warning: no such sysroot directory: '/Applications/Xcode'
configure:3745: $? = 1
configure:3783: result: no
configure: failed program was:
| /* confdefs.h */
| #define PACKAGE_NAME "libgpg-error"
| #define PACKAGE_TARNAME "libgpg-error"
| #define PACKAGE_VERSION "1.20"
| #define PACKAGE_STRING "libgpg-error 1.20"
| #define PACKAGE_BUGREPORT "http://bugs.gnupg.org"
| #define PACKAGE_URL ""
| #define PACKAGE "libgpg-error"
| #define VERSION "1.20"
| /* end confdefs.h.  */
| 
| int
| main ()
| {
| 
|   ;
|   return 0;
| }
configure:3788: error: in `/Users/jayaraj/Desktop/ChatSecure-        iOS/Submodules/OTRKit/scripts/build/libgpg-error-1.20':
configure:3790: error: C compiler cannot create executables
See `config.log' for more details

## ---------------- ##
## Cache variables. ##
## ---------------- ##

ac_cv_build=x86_64-apple-darwin15.0.0
ac_cv_env_CC_FOR_BUILD_set=
ac_cv_env_CC_FOR_BUILD_value=
ac_cv_env_CC_set=set
ac_cv_env_CC_value=gcc
ac_cv_env_CFLAGS_set=set
ac_cv_env_CFLAGS_value=' -arch i386 -fPIE -isysroot /Applications/Xcode     3.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator9.1.sdk -I/Users/jayaraj/Desktop/ChatSecure-    iOS/Submodules/OTRKit/scripts/built/i386/include -miphoneos-version-min=8.0'
ac_cv_env_CPPFLAGS_set=
ac_cv_env_CPPFLAGS_value=
ac_cv_env_CPP_set=
ac_cv_env_CPP_value=
ac_cv_env_LDFLAGS_set=set
ac_cv_env_LDFLAGS_value='-L/Users/jayaraj/Desktop/ChatSecure-    iOS/Submodules/OTRKit/scripts/built/i386/lib -fPIE -miphoneos-version-min=8.0'
ac_cv_env_LIBS_set=
ac_cv_env_LIBS_value=
ac_cv_env_build_alias_set=
ac_cv_env_build_alias_value=
ac_cv_env_host_alias_set=set
ac_cv_env_host_alias_value=i386-apple-darwin
ac_cv_env_target_alias_set=
ac_cv_env_target_alias_value=
ac_cv_host=i386-apple-darwin
ac_cv_path_install='/usr/local/bin/ginstall -c'
ac_cv_path_mkdir=/usr/local/bin/gmkdir
ac_cv_prog_AWK=awk
ac_cv_prog_CC=gcc
ac_cv_prog_ac_ct_STRIP=strip
ac_cv_prog_make_make_set=yes
am_cv_make_support_nested_variables=yes

## ----------------- ##
## Output variables. ##
## ----------------- ##

ACLOCAL='${SHELL} /Users/jayaraj/Desktop/ChatSecure-iOS/Submodules/OTRKit/scripts/build/libgpg-error-1.20/build-aux/missing aclocal-1.14'
AMDEPBACKSLASH=''
AMDEP_FALSE=''
AMDEP_TRUE=''
AMTAR='$${TAR-tar}'
AM_BACKSLASH='\'
AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
AM_DEFAULT_VERBOSITY='1'
AM_V='$(V)'
AR=''
AS=''
AUTOCONF='${SHELL} /Users/jayaraj/Desktop/ChatSecure-iOS/Submodules/OTRKit/scripts/build/libgpg-error-1.20/build-aux/missing     autoconf'
AUTOHEADER='${SHELL} /Users/jayaraj/Desktop/ChatSecure-iOS/Submodules/OTRKit/scripts/build/libgpg-error-1.20/build-aux/missing autoheader'
AUTOMAKE='${SHELL} /Users/jayaraj/Desktop/ChatSecure-iOS/Submodules/OTRKit/scripts/build/libgpg-error-1.20/build-aux/missing     automake-1.14'
AWK='awk'
BUILD_DOC_FALSE=''
BUILD_DOC_TRUE=''
BUILD_FILEVERSION=''
BUILD_REVISION=''
BUILD_TIMESTAMP=''
BUILD_VERSION=''
CC='gcc'
CCDEPMODE=''
CC_FOR_BUILD=''
CFLAGS=' -arch i386 -fPIE -isysroot /Applications/Xcode     3.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator9.1.sdk -I/Users/jayaraj/Desktop/ChatSecure-iOS/Submodules/OTRKit/scripts/built/i386/include -miphoneos-version-min=8.0'
CPP=''
CPPFLAGS=''
CROSS_COMPILING_FALSE=''
CROSS_COMPILING_TRUE=''
CYGPATH_W='echo'
DEFS=''
DEPDIR=''
DLLTOOL=''
DSYMUTIL=''
DUMPBIN=''
ECHO_C='\c'
ECHO_N=''
ECHO_T=''
EGREP=''
EXEEXT=''
FGREP=''
FORCE_USE_SYSCFG_FALSE=''
FORCE_USE_SYSCFG_TRUE=''
GETTEXT_MACRO_VERSION=''
GMSGFMT=''
GMSGFMT_015=''
GPG_ERROR_CONFIG_CFLAGS=''
GPG_ERROR_CONFIG_HOST=''
GPG_ERROR_CONFIG_ISUBDIRAFTER=''
GPG_ERROR_CONFIG_LIBS=''
GPG_ERROR_CONFIG_MT_CFLAGS=''
GPG_ERROR_CONFIG_MT_LIBS=''
GREP=''
HAVE_LD_VERSION_SCRIPT_FALSE=''
HAVE_LD_VERSION_SCRIPT_TRUE=''
HAVE_W32CE_SYSTEM_FALSE=''
HAVE_W32CE_SYSTEM_TRUE=''
HAVE_W32_SYSTEM_FALSE=''
HAVE_W32_SYSTEM_TRUE=''
HAVE_W64_SYSTEM_FALSE=''
HAVE_W64_SYSTEM_TRUE=''
INSTALL_DATA='${INSTALL} -m 644'
INSTALL_PROGRAM='${INSTALL}'
INSTALL_SCRIPT='${INSTALL}'
INSTALL_STRIP_PROGRAM='$(install_sh) -c -s'
INTLLIBS=''
INTL_MACOSX_LIBS=''
LANGUAGES_SOME_FALSE=''
LANGUAGES_SOME_TRUE=''
LD=''
LDFLAGS='-L/Users/jayaraj/Desktop/ChatSecure-iOS/Submodules/OTRKit/scripts/built/i386/lib -fPIE -miphoneos-version-min=8.0'
LIBGPG_ERROR_LT_AGE='16'
LIBGPG_ERROR_LT_CURRENT='16'
LIBGPG_ERROR_LT_REVISION='0'
LIBICONV=''
LIBINTL=''
LIBMULTITHREAD=''
LIBOBJS=''
LIBS=''
LIBTHREAD=''
LIBTOOL=''
LIPO=''
LN_S=''
LTLIBICONV=''
LTLIBINTL=''
LTLIBMULTITHREAD=''
LTLIBOBJS=''
LTLIBTHREAD=''
MAINT='#'
MAINTAINER_MODE_FALSE=''
MAINTAINER_MODE_TRUE='#'
MAKEINFO='${SHELL} /Users/jayaraj/Desktop/ChatSecure-    iOS/Submodules/OTRKit/scripts/build/libgpg-error-1.20/build-aux/missing     makeinfo'
MANIFEST_TOOL=''
MKDIR_P='/usr/local/bin/gmkdir -p'
MSGFMT=''
MSGFMT_015=''
MSGMERGE=''
NM=''
NMEDIT=''
OBJDUMP=''
OBJEXT=''
OTOOL64=''
OTOOL=''
PACKAGE='libgpg-error'
PACKAGE_BUGREPORT='http://bugs.gnupg.org'
PACKAGE_NAME='libgpg-error'
PACKAGE_STRING='libgpg-error 1.20'
PACKAGE_TARNAME='libgpg-error'
PACKAGE_URL=''
PACKAGE_VERSION='1.20'
PATH_SEPARATOR=':'
POSUB=''
RANLIB=''
RC=''
SED=''
SET_MAKE=''
SHELL='/bin/sh'
STRIP='strip'
USE_NLS=''
VERSION='1.20'
VERSION_NUMBER='0x011400'
XGETTEXT=''
XGETTEXT_015=''
XGETTEXT_EXTRA_OPTIONS=''
ac_ct_AR=''
ac_ct_CC=''
ac_ct_DUMPBIN=''
am__EXEEXT_FALSE=''
am__EXEEXT_TRUE=''
am__fastdepCC_FALSE=''
am__fastdepCC_TRUE=''
am__include=''
am__isrc=''
am__leading_dot='.'
am__nodep=''
am__quote=''
am__tar='$${TAR-tar} chof - "$$tardir"'
am__untar='$${TAR-tar} xf -'
bindir='${exec_prefix}/bin'
build='x86_64-apple-darwin15.0.0'
build_alias=''
build_cpu='x86_64'
build_os='darwin15.0.0'
build_vendor='apple'
datadir='${datarootdir}'
datarootdir='${prefix}/share'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
dvidir='${docdir}'
exec_prefix='NONE'
host='i386-apple-darwin'
host_alias='i386-apple-darwin'
host_cpu='i386'
host_os='darwin'
host_vendor='apple'
htmldir='${docdir}'
includedir='${prefix}/include'
infodir='${datarootdir}/info'
install_sh='${SHELL} /Users/jayaraj/Desktop/ChatSecure-    iOS/Submodules/OTRKit/scripts/build/libgpg-error-1.20/build-aux/install-sh'
libdir='${exec_prefix}/lib'
libexecdir='${exec_prefix}/libexec'
localedir='${datarootdir}/locale'
localstatedir='${prefix}/var'
mandir='${datarootdir}/man'
mkdir_p='$(MKDIR_P)'
oldincludedir='/usr/include'
pdfdir='${docdir}'
prefix='/Users/jayaraj/Desktop/ChatSecure-    iOS/Submodules/OTRKit/scripts/build/iPhoneSimulator-9.1-i386'
program_transform_name='s,x,x,'
psdir='${docdir}'
sbindir='${exec_prefix}/sbin'
sharedstatedir='${prefix}/com'
sysconfdir='${prefix}/etc'
target_alias=''

## ----------- ##
## confdefs.h. ##
## ----------- ##

/* confdefs.h */
#define PACKAGE_NAME "libgpg-error"
#define PACKAGE_TARNAME "libgpg-error"
#define PACKAGE_VERSION "1.20"
#define PACKAGE_STRING "libgpg-error 1.20"
#define PACKAGE_BUGREPORT "http://bugs.gnupg.org"
#define PACKAGE_URL ""
#define PACKAGE "libgpg-error"
#define VERSION "1.20"

configure: exit 77

但是这不符合您的要求。

上下文函数是一种在堆栈上放置特定返回地址的方法。

  • getcontext将下一条指令的地址捕获到struct
  • makecontext将结构中的地址更改为其函数参数
  • 的地址
  • setcontext / swapcontext将地址放在堆栈中的结构中并返回给它

上面的程序只有一个控制线程。我认为你真的想要多个线程,在这种情况下你不会使用这些上下文函数。

有关堆栈和C调用约定的更多信息,Eli Bendersky有两篇很好的文章和图表:

FWIW,为了在上面的代码中得到0x26常量,我不得不反汇编main来找到setcontext调用后的第一个地址。

答案 1 :(得分:0)

在您提供的链接中,他们说

  

uc_link 成员用于确定应该是的上下文   当 makecontext ()返回的上下文返回时,恢复。

由于您的程序没有恢复(执行) makecontext ()修改的任何上下文,上述内容不适用,程序结束而不恢复任何上下文。< / p>

要达到你想要的效果,你必须定义一些像

这样的功能
    void main_context()
    {
        // do everything you yet wanted to do in main()
        puts("finished main");
    }

并替换

    return 0;

    char st0[8192];
    ctx[0].uc_stack.ss_sp = st0;
    ctx[0].uc_stack.ss_size = sizeof st0;
    makecontext(&ctx[0], main_context, 0);
    return -setcontext(&ctx[0]);