这篇文章介绍Linux下线程的创建与基本使用案例,主要是案例代码为主;相关的函数详细介绍在上篇文章里已经介绍过了。
1. 案例代码: 线程的创建
下面这份代码演示如何创建线程。在编译的时候需要加上-lpthread
函数原型:
代码语言:javascript复制#include <pthread.h>
int pthread_create
(
pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (void *),
void *arg
);
示例代码:
代码语言:javascript复制#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. 如何接收子线程的返回值?
线程运行的时候默认是结合模式,也可以设置成分离模式,如果是默认的模式,在线程执行完毕后需要回收资源,顺便可以介绍子线程结束时,返回的状态值。
函数原型:
代码语言:javascript复制int pthread_join(pthread_t thread, void **retval);
示例代码:
代码语言:javascript复制#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("主线程正常终止.子线的返回值:%sn",p);
return 0;
}
3. 设置线程的分离属性
默认情况下,子线程是结合模式,需要手动等待子线程结束,清理空间;子线程也支持设置为分离属性,在子线程运行结束后,自己清理空间,下面的例子就演示如何设置子线程为分离模式。
函数原型:
代码语言:javascript复制int pthread_detach(pthread_t thread);
示例代码:
代码语言:javascript复制#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. 注册线程的清理函数
线程清理函数,可以在线程退出时自动调用或者手动调用,用于清理一些需要释放的资源。
函数原型:
代码语言:javascript复制//注册
void pthread_cleanup_push(void (*routine)(void *),void *arg);
//释放
void pthread_cleanup_pop(int execute);
示例代码:
代码语言:javascript复制#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 创建线程时,若不指定分配堆栈大小,系统会分配默认值,查看默认值方法如下:
代码语言:javascript复制[root@tiny4412 ]#ulimit -s
10240
上面的10240单位是KB,也就是默认的线程栈空间大小为10M
也可以通过ulimit -a命令查看,其中的stack size也表示栈空间大小。
代码语言:javascript复制[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 <栈空间大小>
代码语言:javascript复制[root@tiny4412 ]#ulimit -s 8192 //设置栈空间大小
[root@tiny4412 ]#ulimit -s //查看栈空间大小
8192 //大小为8M
注意: 栈空间设置只能在超级管理员用户权限下设置。
每个线程的栈空间都是独立的,如果栈空间溢出程序会出现段错误。如果一个进程有10个线程,那么分配的栈空间大小就是10*<每个线程栈大小>
例如:
代码语言:javascript复制int main(int argc,char **argv)
{
char buff[1024*1024*10]; //在栈空间定义数组,如果超出了栈空间总大小程序会奔溃。
printf("hello world!n");
return 0;
}