菜单

Cobalt/Thread management

详细描述

Cobalt(POSIX)线程管理服务。


函数文档

pthread_create()

int pthread_create(pthread_t *ptid_r, const pthread_attr_t *attr, void *(*start)(void *), void *arg)

创建新线程。

此服务在双内核配置中创建由 Cobalt 核心管理的线程。

新线程的属性取决于 attr 参数。如果 attr 为 NULL,则使用这些属性的默认值。

start 例程返回的效果与调用 pthread_exit() 并传递返回值相同。

参数:

  • ptid_r: 成功时存储新线程标识符的地址;
  • attr: 线程属性;
  • start: 线程启动例程;
  • arg: 传递给 start 的用户提供的不透明参数。

返回值:

  • 成功时返回 0
  • 出错时返回错误号:
    • EINVAL: attr 无效;
    • EAGAIN: 系统堆内存不足,无法创建新线程,请增加 CONFIG_XENO_OPT_SYS_HEAPSZ
    • EINVAL: 线程属性 inheritsched 设置为 PTHREAD_INHERIT_SCHED,且调用线程不属于 Cobalt 接口。

注意:
首次创建 Cobalt 线程时,libcobalt 会为 SIGSHADOW 信号安装一个内部处理程序。如果您之前为该信号安装了处理程序,则该处理程序将仅在 Xenomai 未发送 SIGSHADOW 时被调用。

但是,如果之后安装了应用程序定义的 SIGSHADOW 处理程序,覆盖了 libcobalt 处理程序,则新处理程序需要在进入时调用 cobalt_sigshadow_handler()。此例程对于每次由 Cobalt 核心发出的 SIGSHADOW 返回非零值。如果返回零,则应用程序定义的处理程序应处理该信号。

c 复制代码
int cobalt_sigshadow_handler(int sig, siginfo_t *si, void *ctxt);

您应使用 sigaction(2) 注册处理程序,并设置 SA_SIGINFO 标志。

标签:

  • thread-unrestrictedswitch-secondary

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

// 线程要执行的函数
void* thread_function(void* arg) {
    int thread_id = *((int*)arg);
    printf("Thread%d is running\n", thread_id);
    sleep(1);  // 模拟一些工作
    printf("Thread%d finished\n", thread_id);
    return NULL;
}

int main() {
    pthread_t threads[5]; // 创建5个线程
    int thread_ids[5];    // 用于存储线程ID

    for (int i = 0; i < 5; i++) {
        thread_ids[i] = i; // 设置线程ID
        // 创建线程
        if (pthread_create(&threads[i], NULL, thread_function, &thread_ids[i]) != 0) {
            perror("pthread_create");
            return 1;
        }
    }

    // 等待所有线程结束
    for (int i = 0; i < 5; i++) {
        pthread_join(threads[i], NULL);
    }

    printf("Thread Work Finished\n");
    return 0;
}

pthread_join()

int pthread_join(pthread_t thread, void **ret_val)

等待指定线程终止。

如果 thread 正在运行且可连接,此服务将阻塞调用者,直到 thread 终止或分离。当 thread 终止时,调用者将被解除阻塞,并将其返回值存储在 ret_val 指向的地址中。

另一方面,如果 thread 已经完成执行,其先前收集的返回值将存储在 ret_val 指向的地址中,并且此服务将立即返回。

对于 Cobalt 线程,此服务是一个取消点:如果调用线程在调用此服务时被取消,则取消请求将被接受,并且 thread 仍然是可连接的。

多个同时调用 pthread_join() 指定相同运行目标线程的调用者将全部阻塞,直到目标线程终止。

参数:

  • thread: 要等待的线程标识符;
  • ret_val: 成功时存储目标线程返回值的地址。

返回值:

  • 成功时返回 0
  • 出错时返回错误号:
    • ESRCH: thread 无效;
    • EDEADLK: 尝试连接调用线程自身;
    • EINVAL: thread 已分离;
    • EPERM: 调用者上下文无效。

标签:

  • xthread-onlyswitch-secondaryswitch-primary

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

// 线程要执行的函数
void* thread_function(void* arg) {
    int thread_id = *((int*)arg);
    printf("Thread%d is running\n", thread_id);
    sleep(1);  // 模拟一些工作
    printf("Thread%d finished\n", thread_id);
    return NULL;
}

int main() {
    pthread_t threads[5]; // 创建5个线程
    int thread_ids[5];    // 用于存储线程ID

    for (int i = 0; i < 5; i++) {
        thread_ids[i] = i; // 设置线程ID
        // 创建线程
        if (pthread_create(&threads[i], NULL, thread_function, &thread_ids[i]) != 0) {
            perror("pthread_create");
            return 1;
        }
    }

    // 等待所有线程结束
    for (int i = 0; i < 5; i++) {
        pthread_join(threads[i], NULL);
    }

    printf("Thread Work Finished\n");
    return 0;
}

pthread_kill()

int pthread_kill(pthread_t thread, int sig)

向线程发送信号。

此服务向 Cobalt 线程 thread(通过 pthread_create() 创建)发送信号 sig。如果 sig 为零,此服务将检查线程 thread 的存在性,但不会发送任何信号。

参数:

  • thread: 线程标识符;
  • sig: 信号编号。

返回值:

  • 成功时返回 0
  • 出错时返回错误号:
    • EINVAL: sig 是无效的信号编号;
    • EAGAIN: 超过了最大挂起信号数;
    • ESRCH: thread 是无效的线程标识符。

标签:

  • thread-unrestrictedswitch-primary

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <cobalt/wrappers.h>
pthread_t thread1,thread2;

void *thread_function1(void *arg) {
    // 初始化信号集
    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, SIGQUIT);
    int sig;
    
    printf("Thread1 started, waiting for signal...\n");
    // 阻塞并等待信号
    if(sigwait(&set,&sig) == 0)
    {
        printf("thread1 get SIGQUIT signal\n");
    }else{
        perror("sigwait");
    } 
    printf("Thread1 finished.\n");
    return NULL;
}
void *thread_function2(void *arg) {
    // 初始化信号集
    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, SIGUSR1);
    int sig;

    printf("Thread2 started, waiting for signal...\n");
    // 阻塞并等待信号
    if(sigwait(&set,&sig) == 0)
    {
        printf("thread2 get SIGUSR1 signal\n");
    }else{
        perror("sigwait");
    }
    printf("Thread2 finished.\n");
    return NULL;
}

int main() {
    // 创建线程
    if (pthread_create(&thread1, NULL, thread_function1, NULL) != 0) {
        perror("Failed to create thread");
        return 1;
    }
    if (pthread_create(&thread2, NULL, thread_function2, NULL) != 0) {
        perror("Failed to create thread");
        return 1;
    }

    sleep(1);
    // 发送信号给Thread1
    pthread_kill(thread1, SIGQUIT);
    // 发送信号给Thread2
    pthread_kill(thread2, SIGUSR1);
    // 等待线程结束
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    return 0;
}

pthread_setmode_np()

int pthread_setmode_np(int clrmask, int setmask, int *mode_r)

设置当前线程的模式。

此服务设置调用线程的模式,影响其在特定情况下的行为。clrmasksetmask 是两个模式位掩码,分别由 pthread_setmode_np() 清除和设置。

  • PTHREAD_LOCK_SCHED: 设置时,锁定调度器,防止当前线程被切换出去,直到调度器被解锁。除非同时设置了 PTHREAD_DISABLE_LOCKBREAK,线程仍可能阻塞,暂时释放锁,在这种情况下,当线程恢复执行时,锁将自动重新获取。
  • PTHREAD_WARNSW: 设置时,为当前线程启用调试通知。当检测到以下典型或异常行为时,会发送 SIGDEBUG 信号(源自 Linux)。
  • PTHREAD_DISABLE_LOCKBREAK: 禁止打破调度器锁。通常,当当前所有者阻塞时,调度器锁会隐式释放,然后在恢复执行时自动重新获取。
  • PTHREAD_CONFORMING: 可以在 setmask 中传递,以将当前 Cobalt 线程切换到其首选的运行模式。

此服务是 Cobalt 接口的非可移植扩展。

参数:

  • clrmask: 要清除的位集合。
  • setmask: 要设置的位集合。
  • mode_r: 如果非 NULL,mode_r 必须是一个指向内存位置的指针,成功时将写入先前的活动模式位集合。

返回值:

  • 成功时返回 0,否则:
    • EINVAL: clrmasksetmask 中的某些位无效。

注意:

  • clrmasksetmask 设置为零会导致无操作,仅在 mode_r 是有效地址时返回先前的模式。

注意:

  • 在常规应用中使用 PTHREAD_CONFORMING 很可能是无用的,甚至会引入纯粹的开销。

标签:

  • xthread-onlyswitch-primary

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <cobalt/sched.h>
#include <cobalt/pthread.h>
#include <unistd.h>
#include <string.h>

void* thread_function(void* arg) {
    int thread_id = *(int*)arg;
    printf("Thread %d is running...\n", thread_id);
    sleep(2);
    return NULL;
}

int main() {
    pthread_t thread1, thread2;
    int thread_id1 = 1, thread_id2 = 2;
    
    // 创建第一个线程
    if (pthread_create(&thread1, NULL, thread_function, &thread_id1) != 0) {
        perror("Failed to create thread 1");
        return 1;
    }
    
    // 创建第二个线程
    if (pthread_create(&thread2, NULL, thread_function, &thread_id2) != 0) {
        perror("Failed to create thread 2");
        return 1;
    }
    int mode = 0;
    // 设置当前线程的模式
    if (pthread_setmode_np(PTHREAD_WARNSW|PTHREAD_LOCK_SCHED, 0, &mode) != 0) {
        perror("pthread_setmode_np");
        return 1;
    }

    // 等待线程结束
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    
    // 取消线程模式
    if (pthread_setmode_np(0, PTHREAD_WARNSW|PTHREAD_LOCK_SCHED, &mode) != 0) {
        perror("pthread_setmode_np");
        return 1;
    }

    printf("Both threads have finished execution.\n");
    
    return 0;
}

pthread_setname_np()

int pthread_setname_np(pthread_t thread, const char *name)

设置线程名称。

此服务将线程 thread 的名称设置为 name。该名称用于在 /proc/xenomai/sched 中显示信息。

此服务是 Cobalt 接口的非可移植扩展。

参数:

  • thread: 目标线程。
  • name: 线程名称。

返回值:

  • 成功时返回 0,否则:
    • ESRCH: thread 无效。

标签:

  • xthread-only

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>

void* thread_function(void* arg) {
    printf("Thread %ld is running...\n", (long)arg);
    sleep(10);
    return NULL;
}

int main() {
    pthread_t thread;
    const char* thread_name = "Sinsegye";

    // 创建线程
    if (pthread_create(&thread, NULL, thread_function, (void*)1) != 0) {
        perror("Failed to create thread");
        return 1;
    }

    // 设置线程名称
    if (pthread_setname_np(thread, thread_name) != 0) {
        perror("Failed to set thread name");
        return 1;
    }

    // 等待线程结束
    pthread_join(thread, NULL);
    printf("Thread has finished execution.\n");

    return 0;
}

最近修改: 2025-07-24