POSIX pthread 编程

2023-11-24

我必须编写一个多线程(比如 2 个线程)程序,其中每个线程执行不同的任务。此外,这些线程一旦启动就必须在后台无限运行。这是我所做的。如果方法好或者您发现一些问题,有人可以给我一些反馈吗?另外,我想知道如何在使用 Ctrl+C 终止执行后以系统的方式关闭线程。

main 函数创建两个线程并让它们无限运行,如下所示。

这是骨架:

void    *func1();
void    *func2();

int main(int argc, char *argv[])
{   

    pthread_t th1,th2;
    pthread_create(&th1, NULL, func1, NULL);
    pthread_create(&th2, NULL, func2, NULL);

    fflush (stdout);
    for(;;){
    }
    exit(0); //never reached
}

void *func1()
{
    while(1){
    //do something
    }
}

void *func2()
{
    while(1){
    //do something
    }
} 

Thanks.

使用答案中的输入编辑代码:我是否正确退出线程?

#include <stdlib.h>     /*  exit() */
#include <stdio.h>      /* standard in and output*/
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <signal.h>
#include <semaphore.h>

sem_t end;

void    *func1();
void    *func2();

void ThreadTermHandler(int signo){
    if (signo == SIGINT) {
        printf("Ctrl+C detected !!! \n");
        sem_post(&end);
        }
}
void *func1()
{
    int value;
    for(;;){
        sem_getvalue(&end, &value);
        while(!value){
            printf("in thread 1 \n");
        }
    }
    return 0;
}

void *func2()
{
    int value;
    for(;;){
        sem_getvalue(&end, &value);
        while(!value){
            printf("value = %d\n", value);
        }
    }
    return 0;
}

int main(int argc, char *argv[])
{


    sem_init(&end, 0, 0);
    pthread_t th1,th2;
    int value  = -2;
    pthread_create(&th1, NULL, func1, NULL);
    pthread_create(&th2, NULL, func2, NULL);

    struct sigaction sa;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = ThreadTermHandler;
    // Establish a handler to catch CTRL+c and use it for exiting.
    if (sigaction(SIGINT, &sa, NULL) == -1) {
        perror("sigaction for Thread Termination failed");
        exit( EXIT_FAILURE );
    }

    /* Wait for SIGINT. */
    while (sem_wait(&end)!=0){}
    //{
        printf("Terminating Threads.. \n");
        sem_post(&end);
                sem_getvalue(&end, &value);
        /* SIGINT received, cancel threads. */
        pthread_cancel(th1);
        pthread_cancel(th2);
        /* Join threads. */
        pthread_join(th1, NULL);
        pthread_join(th2, NULL);
    //}
    exit(0);
}

线程终止主要有两种方法。

  • 使用取消点。当请求取消时线程将终止and它到达取消点,从而以受控方式结束执行;
  • 使用信号。让线程安装一个信号处理程序,该处理程序提供终止机制(设置标志并对EINTR).

两种方法都有警告。参考杀死 Pthread 库中的线程更多细节。

就您而言,这似乎是使用取消积分的好机会。我将使用一个带注释的示例。为了清楚起见,省略了错误检查。

#define _POSIX_C_SOURCE 200809L
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void sigint(int signo) {
    (void)signo;
}

void *thread(void *argument) {
    (void)argument;
    for (;;) {
        // Do something useful.
        printf("Thread %u running.\n", *(unsigned int*)argument);

        // sleep() is a cancellation point in this example.
        sleep(1);
    }
    return NULL;
}

int main(void) {
    // Block the SIGINT signal. The threads will inherit the signal mask.
    // This will avoid them catching SIGINT instead of this thread.
    sigset_t sigset, oldset;
    sigemptyset(&sigset);
    sigaddset(&sigset, SIGINT);
    pthread_sigmask(SIG_BLOCK, &sigset, &oldset);

    // Spawn the two threads.
    pthread_t thread1, thread2;
    pthread_create(&thread1, NULL, thread, &(unsigned int){1});
    pthread_create(&thread2, NULL, thread, &(unsigned int){2});

    // Install the signal handler for SIGINT.
    struct sigaction s;
    s.sa_handler = sigint;
    sigemptyset(&s.sa_mask);
    s.sa_flags = 0;
    sigaction(SIGINT, &s, NULL);

    // Restore the old signal mask only for this thread.
    pthread_sigmask(SIG_SETMASK, &oldset, NULL);

    // Wait for SIGINT to arrive.
    pause();

    // Cancel both threads.
    pthread_cancel(thread1);
    pthread_cancel(thread2);

    // Join both threads.
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    // Done.
    puts("Terminated.");
    return EXIT_SUCCESS;
}

阻塞/解除阻塞信号的需要是,如果您向进程发送 SIGINT,任何线程都可能能够捕获它。您可以在生成线程之前执行此操作,以避免它们自己执行此操作并需要与父级同步。创建线程后,恢复掩码并安装处理程序。

如果线程分配大量资源,取消点可能会很棘手;在这种情况下,你将不得不使用pthread_cleanup_push() and pthread_cleanup_pop(),这是一团糟。但如果使用得当,这种方法是可行的,而且相当优雅。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

POSIX pthread 编程 的相关文章

  • 使用 gcc 在 Linux 上运行线程构建块 (Intel TBB)

    我正在尝试为线程构建块构建一些测试 不幸的是 我无法配置 tbb 库 链接器找不到库 tbb 我尝试在 bin 目录中运行脚本 但这没有帮助 我什至尝试将库文件移动到 usr local lib 但这又失败了 任何的意见都将会有帮助 确定您
  • WPF DataGrid 多选

    我读过几篇关于这个主题的文章 但很多都是来自 VS 或框架的早期版本 我想做的是从 dataGrid 中选择多行并将这些行返回到绑定的可观察集合中 我尝试创建一个属性 类型 并将其添加到可观察集合中 它适用于单个记录 但代码永远不会触发多个
  • 根据属性的类型使用文本框或复选框

    如果我有这样的结构 public class Parent public string Name get set public List
  • 如何在 C# 中打开 Internet Explorer 属性窗口

    我正在开发一个 Windows 应用程序 我必须向用户提供一种通过打开 IE 设置窗口来更改代理设置的方法 Google Chrome 使用相同的方法 当您尝试更改 Chrome 中的代理设置时 它将打开 Internet Explorer
  • -webkit-box-shadow 与 QtWebKit 模糊?

    当时有什么方法可以实现 webkit box shadow 的工作模糊吗 看完这篇评论错误报告 https bugs webkit org show bug cgi id 23291 我认识到这仍然是一个问题 尽管错误报告被标记为RESOL
  • 无限循环与无限递归。两者都是未定义的吗?

    无副作用的无限循环是未定义的行为 看here https coliru stacked crooked com view id 24e0a58778f67cd4举个例子参考参数 https en cppreference com w cpp
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • 重载 (c)begin/(c)end

    我试图超载 c begin c end类的函数 以便能够调用 C 11 基于范围的 for 循环 它在大多数情况下都有效 但我无法理解和解决其中一个问题 for auto const point fProjectData gt getPoi
  • ASP.NET Core 3.1登录后如何获取用户信息

    我试图在登录 ASP NET Core 3 1 后获取用户信息 如姓名 电子邮件 id 等信息 这是我在登录操作中的代码 var claims new List
  • C# - 当代表执行异步任务时,我仍然需要 System.Threading 吗?

    由于我可以使用委托执行异步操作 我怀疑在我的应用程序中使用 System Threading 的机会很小 是否存在我无法避免 System Threading 的基本情况 只是我正处于学习阶段 例子 class Program public
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • x:将 ViewModel 方法绑定到 DataTemplate 内的事件

    我基本上问同样的问题这个人 https stackoverflow com questions 10752448 binding to viewmodels property from a template 但在较新的背景下x Bind V
  • 如何在 Linq to SQL 中使用distinct 和 group by

    我正在尝试将以下 sql 转换为 Linq 2 SQL select groupId count distinct userId from processroundissueinstance group by groupId 这是我的代码
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • C++ 继承的内存布局

    如果我有两个类 一个类继承另一个类 并且子类仅包含函数 那么这两个类的内存布局是否相同 e g class Base int a b c class Derived public Base only functions 我读过编译器无法对数
  • 为什么 std::uint32_t 与 uint32_t 不同?

    我对 C 有点陌生 我有一个编码作业 很多文件已经完成 但我注意到 VS2012 似乎有以下语句的问题 typedef std uint32 t identifier 不过 似乎将其更改为 typedef uint32 t identifi
  • C++ 中的参考文献

    我偶尔会在 StackOverflow 上看到代码 询问一些涉及函数的重载歧义 例如 void foo int param 我的问题是 为什么会出现这种情况 或者更确切地说 你什么时候会有 对参考的参考 这与普通的旧参考有何不同 我从未在现
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲

随机推荐

  • scipy中样条插值的系数

    我想通过 scipy 计算样条插值的系数 在 MATLAB 中 x 0 3 y 0 1 4 0 spl spline x y disp spl coefs 它会返回 ans 1 5000 5 5000 3 0000 0 1 5000 1 0
  • 在 Javascript contenteditable div 中插入文本

    有没有办法将文本 字符串 可能有也可能没有 html 标签 插入到div 它必须是一个div而不是一个textarea 首先 我需要获取光标位置 然后在该位置插入文本 和函数类似insertAdjacentText 但只能在标签之前或之后插
  • VS调试问题,谁能帮我解释一下?

    一段C 代码 var isTrue new List
  • 压缩字体以在网络中使用

    在用作网络字体之前可以对字体进行某种压缩吗 我有一个 150kB 的字体文件 能不能压缩一下 而且如果我要求两种字体 eot and ttf两者都会被浏览器下载吗 如果您使用 FontSquirrel font face 套件生成器 htt
  • WSO2 ESB DBLookup 中介查询多行

    正如 DBLookup Mediator 的文档中所述 它仅返回查询的第一行 其他结果 如果有 将被忽略 我想知道是否有 最佳方法 来运行返回多个记录然后处理它们的查询 SELECT FROM X 现在我们正在实现 axis2 服务 但是还
  • 正则表达式匹配文件夹和所有子文件夹

    我需要为备份排除过滤器编写正则表达式以排除文件夹及其所有子文件夹 我需要匹配以下内容 folder1 statistics folder1 statistics folder2 statistics folder2 statistics 我
  • XGBoost - 具有不同曝光/偏移的泊松分布

    我正在尝试使用 XGBoost 对不等长的暴露期生成的数据的索赔频率进行建模 但无法让模型正确处理暴露 我通常会通过将 log exposure 设置为偏移量来做到这一点 你能在 XGBoost 中做到这一点吗 这里发布了类似的问题 xgb
  • firebase 身份验证/无效的自定义令牌

    我正在尝试使用 firebase admin sdk 生成自定义令牌 const uid 91f0bf4c 3e3c 441c a21d 6a7fee341db5 firebaseAdmin auth createCustomToken u
  • 如何训练 libsvm 格式的图像(像素)数据以用于 Java 识别

    我想制作一个 Java 应用程序来使用 libsvm 来识别字符 但是当进入这个过程时 我不明白如何训练图像数据以与 libsvm 一起使用 最近为了学习它 我做了一个测试现有数据 我也创建了32x32基于训练图像数据 将每个像素转换为0
  • C++:如何创建一个接受连接字符串作为参数的函数?

    我可以以某种方式设计我的日志记录功能 使其接受使用 C 的以下形式的串联字符串吗 int i 1 customLoggFunction My Integer i lt lt i lt lt customLoggFunction std co
  • SSIS 中的 UPSERT

    我正在编写一个在 SQL Server 2008 上运行的 SSIS 包 如何在 SSIS 中执行 UPSERT IF KEY NOT EXISTS INSERT ELSE IF DATA CHANGED UPDATE ENDIF ENDI
  • 如何使用 JavaBeans 集合数据集填充图表数据?

    我已经创建了一个工作 jrxml 报告 其中显示了一个由集合的数据集填充的表 List 的 Java bean 现在我想使用相同的数据集来创建图表 初学者的基本条形图 每个 bean 包含 4 个我想在条形图上显示的值 月份 正常时间 旅行
  • `all: unset` 和 `all: revert' 有什么区别

    根据 MDN 在许多情况下 revert 关键字的工作方式与 unset 完全相同 这 唯一的区别是具有由浏览器设置值的属性 或由用户创建的自定义样式表 在浏览器端设置 我不明白浏览器和自定义样式表 浏览器和自定义样式表都可以替换为all
  • Docker-Compose持久数据MySQL

    如果我运行 我似乎无法让 MySQL 数据持久化 docker compose down与以下 yml version 2 services other services data container name flask data ima
  • (如何)我可以计算枚举中的项目吗?

    当我有类似的事情时 我想到了这个问题 enum Folders FA FB FC 并想为每个文件夹创建一个容器数组 ContainerClass m containers 3 m containers FA etc 使用地图会更优雅 std
  • WebDriver Selenium API:当 Element 明显存在时,出现 ElementNotFoundErrorException!

    有时 在关闭 Javascript 的情况下在 WebDriver 上运行测试时 WebDriver 在找到某个元素并尝试单击它时会因 ElementNotFound 错误而崩溃 然而 这个元素显然是存在的 读完这篇文章后 http cod
  • 制作使用项目字段作为键的查找表的惯用方法是什么?

    我有一个收藏Foo struct Foo k String v String 我想要一个HashMap哪个有钥匙 foo k和价值foo 显然 不重新设计是不可能的Foo通过介绍Rc或克隆 复制k fn t1 let foo Foo k k
  • 迁移期间 Laravel 未配置数据库

    这可能是重复的问题 但我对以前的答案没有运气 I just git clone一个 Laravel 项目 现在我尝试做php artisan migrate 它返回以下错误 InvalidArgumentException Database
  • .NET 中的引用是如何定位的?

    NET 使用什么过程在运行时定位引用的程序集 它与在编译期间定位引用的程序集的过程是否不同 我对搜索的位置及其搜索顺序以及可能影响结果的任何参数 配置设置特别感兴趣 NET 应用程序中可以进行三种类型的引用 此答案仅涵盖下面列表中的前两个
  • POSIX pthread 编程

    我必须编写一个多线程 比如 2 个线程 程序 其中每个线程执行不同的任务 此外 这些线程一旦启动就必须在后台无限运行 这是我所做的 如果方法好或者您发现一些问题 有人可以给我一些反馈吗 另外 我想知道如何在使用 Ctrl C 终止执行后以系