Linux系统编程-(pthread)线程的使用案例(分离属性、清理函数等)

简介: 这篇文章介绍Linux下线程的创建与基本使用案例,主要是案例代码为主;相关的函数详细介绍在上篇文章里已经介绍过了。

这篇文章介绍Linux下线程的创建与基本使用案例,主要是案例代码为主;相关的函数详细介绍在上篇文章里已经介绍过了。

1. 案例代码: 线程的创建

下面这份代码演示如何创建线程。在编译的时候需要加上-lpthread

函数原型:

#include <pthread.h>
int pthread_create
(
pthread_t *thread, 
const pthread_attr_t *attr,
void *(*start_routine) (void *), 
void *arg
);

示例代码:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>

//[wbyq@wbyq linux_c]$ gcc app.c -lpthread

/*
线程工作函数
*/
void *thread_work_func(void *dev)
{
    int i;
    for(i=0;i<5;i++)
    {
        sleep(1);
        printf("子线程正在运行.%d \n",i);
    }
    //终止当前线程执行
    pthread_exit(NULL);
}

int main(int argc,char **argv)
{
    /*1. 创建子线程*/
    pthread_t thread_id;
    if(pthread_create(&thread_id,NULL,thread_work_func,NULL)!=0)
    {
        printf("子线程创建失败.\n");
        return -1;
    }
    /*2. 等待子线程结束-清理子线程的空间*/
    pthread_join(thread_id,NULL);//--wait
    printf("主线程正常终止.\n");
    return 0;
}

2. 如何接收子线程的返回值?

线程运行的时候默认是结合模式,也可以设置成分离模式,如果是默认的模式,在线程执行完毕后需要回收资源,顺便可以介绍子线程结束时,返回的状态值。

函数原型:

int pthread_join(pthread_t thread, void **retval);

示例代码:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>

//[wbyq@wbyq linux_c]$ gcc app.c -lpthread

/*
线程工作函数
*/
void *thread_work_func(void *dev)
{
    int i;
    for(i=0;i<5;i++)
    {
        sleep(1);
        printf("子线程正在运行.%d \n",i);
    }
    //终止当前线程执行
    pthread_exit("1234567890");
}

int main(int argc,char **argv)
{
    /*1. 创建子线程*/
    pthread_t thread_id;
    if(pthread_create(&thread_id,NULL,thread_work_func,NULL)!=0)
    {
        printf("子线程创建失败.\n");
        return -1;
    }
    /*2. 等待子线程结束-清理子线程的空间*/
    char *p;
    pthread_join(thread_id,&p);//--wait
    printf("主线程正常终止.子线的返回值:%s\n",p);
    return 0;
}

3. 设置线程的分离属性

默认情况下,子线程是结合模式,需要手动等待子线程结束,清理空间;子线程也支持设置为分离属性,在子线程运行结束后,自己清理空间,下面的例子就演示如何设置子线程为分离模式。

函数原型:

int pthread_detach(pthread_t thread);

示例代码:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>

//[wbyq@wbyq linux_c]$ gcc app.c -lpthread

/*
线程工作函数
*/
void *thread_work_func(void *dev)
{
    int i;
    for(i=0;i<5;i++)
    {
        sleep(1);
        printf("子线程正在运行.%d \n",i);
    }
    //终止当前线程执行
    pthread_exit(NULL);
}

int main(int argc,char **argv)
{
    /*1. 创建子线程*/
    pthread_t thread_id;
    if(pthread_create(&thread_id,NULL,thread_work_func,NULL)!=0)
    {
        printf("子线程创建失败.\n");
        return -1;
    }
    /*2. 设置线程的分离属性*/
    pthread_detach(thread_id);
    while(1)
    {
        printf("主线程正在运行.\n");
        sleep(1);
    }
    return 0;
}

4. 注册线程的清理函数

线程清理函数,可以在线程退出时自动调用或者手动调用,用于清理一些需要释放的资源。

函数原型:

//注册
void pthread_cleanup_push(void (*routine)(void *),void *arg); 
//释放
void pthread_cleanup_pop(int execute);

示例代码:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>
#include <pthread.h>

//[wbyq@wbyq linux_c]$ gcc app.c -lpthread

//线程的清理工作函数
void thread_clear_work_func(void *dev)
{
    printf("线程的清理工作函数被调用.\n");
    /*
    做一些资源清理工作。
    比如: 释放malloc申请的空间,关闭打开的文件等等.
    */
}

/*
线程工作函数
*/
void *thread_work_func(void *dev)
{
    int i;
    //注册清理函数
    pthread_cleanup_push(thread_clear_work_func,NULL); 
    for(i=0;i<5;i++)
    {
        sleep(1);
        printf("子线程正在运行.%d \n",i);
    }

    //终止当前线程执行
    pthread_exit(NULL);
    
    //释放清理函数
    pthread_cleanup_pop(1); 
}

int main(int argc,char **argv)
{
    /*1. 创建子线程*/
    pthread_t thread_id;
    if(pthread_create(&thread_id,NULL,thread_work_func,NULL)!=0)
    {
        printf("子线程创建失败.\n");
        return -1;
    }
    /*2. 设置线程的分离属性*/
    pthread_detach(thread_id);
    
    sleep(3);
    //取消指定子线程结束
    pthread_cancel(thread_id);

    while(1)
    {
        printf("主线程正在运行.\n");
        sleep(1);
    }
    return 0;
}

5. 通过ulimit命令设置栈空间大小

pthread_create 创建线程时,若不指定分配堆栈大小,系统会分配默认值,查看默认值方法如下:

[root@tiny4412 ]#ulimit -s
10240

上面的10240单位是KB,也就是默认的线程栈空间大小为10M

也可以通过ulimit -a命令查看,其中的stack size也表示栈空间大小。

[root@tiny4412 ]#ulimit -a
-f: file size (blocks)             unlimited
-t: cpu time (seconds)             unlimited
-d: data seg size (kb)             unlimited
-s: stack size (kb)                10240
-c: core file size (blocks)        0
-m: resident set size (kb)         unlimited
-l: locked memory (kb)             64
-p: processes                      7512
-n: file descriptors               1024
-v: address space (kb)             unlimited
-w: locks                          unlimited
-e: scheduling priority            0
-r: real-time priority             0

设置栈空间大小: ulimit -s <栈空间大小>

[root@tiny4412 ]#ulimit -s 8192   //设置栈空间大小
[root@tiny4412 ]#ulimit -s        //查看栈空间大小
8192                          //大小为8M

注意: 栈空间设置只能在超级管理员用户权限下设置。

每个线程的栈空间都是独立的,如果栈空间溢出程序会出现段错误。如果一个进程有10个线程,那么分配的栈空间大小就是10*<每个线程栈大小>

例如:

int main(int argc,char **argv)
{
    char buff[1024*1024*10];  //在栈空间定义数组,如果超出了栈空间总大小程序会奔溃。
    printf("hello world!\n");
    return 0;
}
目录
相关文章
|
1天前
|
Linux 应用服务中间件 Shell
linux系统服务二!
本文详细介绍了Linux系统的启动流程,包括CentOS 7的具体启动步骤,从BIOS自检到加载内核、启动systemd程序等。同时,文章还对比了CentOS 6和CentOS 7的启动流程,分析了启动过程中的耗时情况。接着,文章讲解了Linux的运行级别及其管理命令,systemd的基本概念、优势及常用命令,并提供了自定义systemd启动文件的示例。最后,文章介绍了单用户模式和救援模式的使用方法,包括如何找回忘记的密码和修复启动故障。
14 5
linux系统服务二!
|
1天前
|
Linux 应用服务中间件 Shell
linux系统服务!!!
本文详细介绍了Linux系统(以CentOS7为例)的启动流程,包括BIOS自检、读取MBR信息、加载Grub菜单、加载内核及驱动程序、启动systemd程序加载必要文件等五个主要步骤。同时,文章还对比了CentOS6和CentOS7的启动流程图,并分析了启动流程的耗时。此外,文中还讲解了Linux的运行级别、systemd的基本概念及其优势,以及如何使用systemd管理服务。最后,文章提供了单用户模式和救援模式的实战案例,帮助读者理解如何在系统启动出现问题时进行修复。
15 3
linux系统服务!!!
|
9天前
|
Web App开发 搜索推荐 Unix
Linux系统之MobaXterm远程连接centos的GNOME桌面环境
【10月更文挑战第21天】Linux系统之MobaXterm远程连接centos的GNOME桌面环境
98 4
Linux系统之MobaXterm远程连接centos的GNOME桌面环境
|
10天前
|
运维 监控 Linux
Linux系统之部署Linux管理面板1Panel
【10月更文挑战第20天】Linux系统之部署Linux管理面板1Panel
55 2
Linux系统之部署Linux管理面板1Panel
|
1天前
|
网络协议 Linux
linux系统重要文件目录
本文介绍了Linux系统中的重要目录及其历史背景,包括根目录、/usr、/etc、/var/log和/proc等目录的结构和功能。其中,/etc目录下包含了许多关键配置文件,如网卡配置、DNS解析、主机名设置等。文章还详细解释了各目录和文件的作用,帮助读者更好地理解和管理Linux系统。
10 2
|
3天前
|
Ubuntu Linux Shell
Linux 系统中的代码类型或脚本类型内容
在 Linux 系统中,代码类型多样,包括 Shell 脚本、配置文件、网络配置、命令行工具和 Cron 定时任务。这些代码类型广泛应用于系统管理、自动化操作、网络配置和定期任务,掌握它们能显著提高系统管理和开发的效率。
|
5天前
|
关系型数据库 MySQL Linux
Linux系统如何设置自启动服务在MySQL数据库启动后执行?
【10月更文挑战第25天】Linux系统如何设置自启动服务在MySQL数据库启动后执行?
40 3
|
7天前
|
运维 监控 Shell
深入理解Linux系统下的Shell脚本编程
【10月更文挑战第24天】本文将深入浅出地介绍Linux系统中Shell脚本的基础知识和实用技巧,帮助读者从零开始学习编写Shell脚本。通过本文的学习,你将能够掌握Shell脚本的基本语法、变量使用、流程控制以及函数定义等核心概念,并学会如何将这些知识应用于实际问题解决中。文章还将展示几个实用的Shell脚本例子,以加深对知识点的理解和应用。无论你是运维人员还是软件开发者,这篇文章都将为你提供强大的Linux自动化工具。
|
8天前
|
存储 安全 关系型数据库
Linux系统在服务器领域的应用与优势###
本文深入探讨了Linux操作系统在服务器领域的广泛应用及其显著优势。通过分析其开源性、安全性、稳定性和高效性,揭示了为何Linux成为众多企业和开发者的首选服务器操作系统。文章还列举了Linux在服务器管理、性能优化和社区支持等方面的具体优势,为读者提供了全面而深入的理解。 ###
|
26天前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
38 1
C++ 多线程之初识多线程