进程与线程的区别
进程拥有独立的地址空间,而且进程间的数据空间也相互独立,数据的传递得通过通信的方式;
线程是在一个进程下同时运行,多个线程之间的数据共享
线程的启动
函数原型:
/* Create a new thread, starting with execution of START-ROUTINE
getting passed ARG. Creation attributed come from ATTR. The new
handle is stored in *NEWTHREAD. */
extern int pthread_create (pthread_t *__restrict __newthread,
const pthread_attr_t *__restrict __attr,
void *(*__start_routine) (void *),
void *__restrict __arg) __THROWNL __nonnull ((1, 3));
第一个参数为指向线程标识符的指针;
第二个参数为线程的属性;
第三个参数是线程运行函数的起始地址;
第四个参数是运行函数的参数;
z注
:返回0表示创建成功,非o创建失败;EAGAIN
表示系统不允许创建(线程数量过多),EINVAL
第二个参数的属性非法
线程的退出
1 线程函数执行完返回
2 调用pthread_exit结束
相关函数
pthread_join
函数
/* Make calling thread wait for termination of the thread TH. The
exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN
is not NULL.
This function is a cancellation point and therefore not marked with
__THROW. */
extern int pthread_join (pthread_t __th, void **__thread_return);
第一个参数为等待的线程的标识符
第二个参数为用户定义的指针,它可以用来存储被等待线程的返回值
注
:这个函数是一个线程阻塞函数,调用它将会一直等着被等带的线程函数执行完返回
pthread_detach
函数
/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN.
The resources of TH will therefore be freed immediately when it
terminates, instead of waiting for another thread to perform PTHREAD_JOIN
on it. */
extern int pthread_detach (pthread_t __th) __THROW;
参数就是线程的标识符,一旦调用该函数,该线程就不能再调用pthread_join加入等待列表,线程函数执行完以后会立即释放资源,使用此函数时一般不关心执行结果。
pthread_exit
函数
/* Terminate calling thread.
The registered cleanup handlers are called via exception handling
so we cannot mark this function with __THROW.*/
extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__));
参数是函数的返回值,只要pthread_join的第二个参数不是NULL,这个值将被传递给__thread_return
注
:一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join的线程返回错误,错误代码:ESRCH
Demo 代码
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "keyboard.h"
#define MAX_THREAD_COUNT 10
typedef struct thread_s {
pthread_t thread; //线程标志符
void *(*start_routine)(void *); //函数指针,需要执行的函数
void *arg; //指针函数的参数
int blocked; //线程运行状态标志
int started; //现场启动标志
} thread_t;
static thread_t threads[MAX_THREAD_COUNT]; //定义一个静态数组存放线程信息
static int thread_cnt = 0; //已有线程的数据
static int quit = 0; //标记是否退出线程
static void add_thread(void *(*start_routine)(void *), void *arg, int blocked) {
if (thread_cnt >= MAX_THREAD_COUNT)
return;
threads[thread_cnt].start_routine = start_routine;
threads[thread_cnt].arg = arg;
threads[thread_cnt].blocked = blocked;
threads[thread_cnt].started = 0;
thread_cnt++;
}
static void start_thread(void) {
int i;
for (i = 0; i < thread_cnt; i++) {
//创建一个线程
if (pthread_create(&threads[i].thread, NULL, threads[i].start_routine,
threads[i].arg) == 0) {
threads[i].started = 1;
} else {
fprintf(stderr, "%s(): cannot create thread %d\n", __FUNCTION__, i);
}
}
}
static void exit_thread(void) {
int i;
for (i = 0; i < thread_cnt; i++) {
if (threads[i].started) {
if (threads[i].blocked)
pthread_kill(threads[i].thread, SIGHUP);
pthread_join(threads[i].thread, NULL);
}
}
}
static void *test_thread_a(void *arg) {
while (!quit) {
//在这里添加需要执行的代码
fprintf(stderr, "%s(): thread is running!\n", __FUNCTION__);
sleep(2);
}
fprintf(stderr, "%s(): thread terminated!\n", __FUNCTION__);
}
static void *test_thread_b(void *arg) {
while (1) {
fprintf(stderr, "%s(): thread is running!\n", __FUNCTION__);
sleep(3);
}
fprintf(stderr, "%s(): thread terminated!\n", __FUNCTION__);
}
int main(int argc, char **argv) {
int _char;
add_thread(test_thread_a, NULL, 0);
add_thread(test_thread_b, NULL, 1);
start_thread();
//初始化键盘输入
if (init_keyboard() != 0) {
fprintf(stderr, "init_keyboard failed\n");
} else {
fprintf(stderr, "Press Q or q quit\n");
}
while (!quit) {
//接收所有键盘输入的字符,如果有Q或者q就退出程序
while ((_char = __getch()) >= 0) {
if (_char == 'Q' || _char == 'q') {
quit = 1;
break;
}
}
sleep(2);
}
close_keyboard();
exit_thread();
return 0;
}