Linux线程(1): 线程的创建
2007-07-31 18:16
246 查看
1. 概念:
线程与进程是不同的, 准确地说, 进程可以由多个线程组成, 线程是进程的组成元素. 默认情况下, 一个进程只是由一个线程构成, 它串行执行该进程要执行的任务. 多线程情况下, 每个线程执行各自的任务, 它们之间更多是并行的. 线程的作用具体有:
在单进程环境中执行多个任务.
共享该进程的组成部件, 如文件描述符和内存, 但需要较为复杂的机制.
同步和异步执行.
线程改善吞吐量, 由串行转化为并行, 交叉执行.
线程的特征测试宏_POSIX_THREADS:
用#ifdef测试上述宏以确定是否支持线程.
用_SC_THREADS常数调用sysconf函数, 以确定是否支持线程
2. 线程标识(ID):
线程有ID, 但不是系统唯一, 而是进程环境中唯一有效.
线程的句柄是pthread_t类型, 该类型不能作为整数处理, 而是一个结构.
下面介绍两个函数:
头文件: <pthread.h>
原型: int pthread_equal(pthread_t tid1, pthread_t tid2);
返回值: 相等返回非0, 不相等返回0.
说明: 比较两个线程ID是否相等.
头文件: <pthread.h>
原型: pthread_t pthread_self();
返回值: 返回调用线程的线程ID.
3. 线程创建:
在执行中创建一个线程, 可以为该线程分配它需要做的工作(线程执行函数), 该线程共享进程的资源. 创建线程的函数pthread_create()
头文件: <pthread.h>
原型: int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(start_rtn)(void), void *restrict arg);
返回值: 成功则返回0, 否则返回错误编号.
参数:
tidp: 指向新创建线程ID的变量, 作为函数的输出.
attr: 用于定制各种不同的线程属性, NULL为默认属性.
start_rtn: 函数指针, 为线程开始执行的函数名.
arg: 函数的唯一无类型(void)指针参数, 如要传多个参数, 可以用结构封装.
4. 实例:
main.c代码:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#include <pthread.h>
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
pthread_t ntid; /**//* save thread ID */
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
/**//* print process ID and thread ID */
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
void printids(const char *s)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
pid_t pid;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
pthread_t tid;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
pid = getpid();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
tid = pthread_self();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
printf(%s pid %d tid %d (0x%x) ", s, pid, tid, tid);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
/**//* thread process func */
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
void *thread_proc(void *arg)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
printids("new thread: ");
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
return NULL;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
/**//* main func */
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
int main()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
int err;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
/**//* create a thread */
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
err = pthread_create(&ntid, NULL, thread_proc, NULL);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
/**//* error handler */
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
if (err != 0)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
perror("can't create thread");
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
printids("main thread: ");
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
sleep(1);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
return 0;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
编译命令:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
gcc -o test main.c -lpthread
在这个例子中, 可能会有人疑问为什么在main中加上sleep, 这是因为主线程需要休眠, 否则可能会比新线程更早退出, 这个在新线程运行前整个进程可能已经终止了. 所以加上sleep让主线程休眠一下, 确保新线程先完成.
在你的Linux中跑一下这个代码, 看看线程ID有什么特点.
线程与进程是不同的, 准确地说, 进程可以由多个线程组成, 线程是进程的组成元素. 默认情况下, 一个进程只是由一个线程构成, 它串行执行该进程要执行的任务. 多线程情况下, 每个线程执行各自的任务, 它们之间更多是并行的. 线程的作用具体有:
在单进程环境中执行多个任务.
共享该进程的组成部件, 如文件描述符和内存, 但需要较为复杂的机制.
同步和异步执行.
线程改善吞吐量, 由串行转化为并行, 交叉执行.
线程的特征测试宏_POSIX_THREADS:
用#ifdef测试上述宏以确定是否支持线程.
用_SC_THREADS常数调用sysconf函数, 以确定是否支持线程
2. 线程标识(ID):
线程有ID, 但不是系统唯一, 而是进程环境中唯一有效.
线程的句柄是pthread_t类型, 该类型不能作为整数处理, 而是一个结构.
下面介绍两个函数:
头文件: <pthread.h>
原型: int pthread_equal(pthread_t tid1, pthread_t tid2);
返回值: 相等返回非0, 不相等返回0.
说明: 比较两个线程ID是否相等.
头文件: <pthread.h>
原型: pthread_t pthread_self();
返回值: 返回调用线程的线程ID.
3. 线程创建:
在执行中创建一个线程, 可以为该线程分配它需要做的工作(线程执行函数), 该线程共享进程的资源. 创建线程的函数pthread_create()
头文件: <pthread.h>
原型: int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(start_rtn)(void), void *restrict arg);
返回值: 成功则返回0, 否则返回错误编号.
参数:
tidp: 指向新创建线程ID的变量, 作为函数的输出.
attr: 用于定制各种不同的线程属性, NULL为默认属性.
start_rtn: 函数指针, 为线程开始执行的函数名.
arg: 函数的唯一无类型(void)指针参数, 如要传多个参数, 可以用结构封装.
4. 实例:
main.c代码:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#include <pthread.h>
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
pthread_t ntid; /**//* save thread ID */
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
/**//* print process ID and thread ID */
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
void printids(const char *s)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
pid_t pid;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
pthread_t tid;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
pid = getpid();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
tid = pthread_self();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
printf(%s pid %d tid %d (0x%x) ", s, pid, tid, tid);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
/**//* thread process func */
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
void *thread_proc(void *arg)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
printids("new thread: ");
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
return NULL;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
/**//* main func */
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
int main()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
int err;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
/**//* create a thread */
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
err = pthread_create(&ntid, NULL, thread_proc, NULL);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
/**//* error handler */
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
if (err != 0)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
perror("can't create thread");
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
printids("main thread: ");
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
sleep(1);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
return 0;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
编译命令:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
gcc -o test main.c -lpthread
在这个例子中, 可能会有人疑问为什么在main中加上sleep, 这是因为主线程需要休眠, 否则可能会比新线程更早退出, 这个在新线程运行前整个进程可能已经终止了. 所以加上sleep让主线程休眠一下, 确保新线程先完成.
在你的Linux中跑一下这个代码, 看看线程ID有什么特点.
相关文章推荐
- poll and epoll的区别-linux C线程间通信:阻塞-唤醒-创建文件,重启后大小是0
- linux创建线程时,需注意线程内存回收问题!
- Linux系统编程:fork函数的使用【循环创建N个子线程】
- linux 创建线程
- 【Linux学习】pthread_create主线程与创建的新线程之间退出关系
- Linux下创建进程线程以及通信技术的使用
- Linux创建线程
- Linux下的多线程编程(一) 创建线程
- Linux创建线程
- Linux下线程的创建
- Linux下共享内存及线程的创建
- 浅析Linux线程的创建
- linux下创建1000个线程?
- Linux进程管理、进程创建、线程实现、僵尸进程
- Unix/Linux创建一个线程
- Linux 线程的创建与结束
- linux上创建线程的类
- Linux多线程编程(一)——线程创建
- 【Linux】线程的创建
- Linux 进程与线程一(创建-关闭线程)