一、线程的定义
进程是资源分配的最小单元,而线程是运行的最小单元,所有的进程至少含有一个可执行的线程。Linux系统是一个多用户多任务的操作系统,学习在Linux下的多进程和多线程的编程对一个Linux系统程序员是很重要的的。在Linux下可以用fork系统调用去创建一个新的进程,可以使用pthread_create系统调用去创建一个线程,创建出来的线程拥有自己的栈用来存放局部变量,但是和主进程共享全局变量、文件描述符等等。
二、线程的编程
1. 创建线程
创建线程需要用到pthread.h文件中提供的pthread_create()函数,该函数的原型如下:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg);
如果线程创建成功将返回0,否则将返回一个失败的代码。
第一个参数pthread_t * thread将保存这个线程的标识符,就好像进程PID的,
第二个参数const pthread_attr_t *attr线程的属性,这个先不说,等到后面再说。
第三个参数指明了这个线程将要从哪里开始执行的,这和fork创建的进程是不一样的,fork创建出来的进程是将原来的进程的所有东西都拷贝到自己的任务空间去了,而且新的进程也有一个PID标识符,它们执行的代码空间是完全一样的只是执行的内容并不一定一样的。但是线程是和主的进程共享代码段的,而且它所执行的代码是由主的进程指定的。
第四个参数是主进程传给线程才参数,因此线程执行的函数必须是只有一个参数的而且类型是void *;
下面就给出一个简单的创建线程的代码:
#include
#include
void *thread_func(void *arg);
main()
{
int res;
pthread_t p_thread;
res = pthread_create(&p_thread, NULL, thread_func, 0);
if(res != 0)
{
printf("创建线程失败\n");
return;
}
}
void *thread_func(void *arg)
{
printf("线程执行。。。。。。。\n");
}
使用下面的命令去编译它 gcc -D_POSIX_C_SOURCE test.c -lpthread
上面这个程序简单的演示了一下如何创建并运行一个简单的线程,在这个程序中主进程利用pthread_create创建了一个线程,然后这个线程就会去执行由函数中第三个参数指定的函数。但是,在上面的程序中主进程和线程之间都是运行自己的代码,并没有体现出线程应有的优势,就是和主进程或者其他的线程协作完成任务。
2. 实现线程和主进程之间协作
下面这个程序将完成主进程向线程传递一个参数,然后主进程等待线程运行结束,并且线程在运行结束的时候也要向主进程传递一个参数。完成这个功能要使用到另外两个函数:
int pthread_join(pthread_t thread, void **value_ptr);这个函数的功能类似于waitpid的功能,它的功能是挂起调用的线程等待目标线程执行完成在执行调用的线程,参数一指定了等待的目标线程,参数二是由目标线程在退出执行时传递的参数。
void pthread_exit(void *value_ptr); 线程退出执行并且传递一个参数给等待他完成的线程。
源码如下:
#include
#include
#include
#include
void *thread_function(void *arg);
char message[] = "Hello World";
int main() {
int res;
pthread_t a_thread;
void *thread_result;
res = pthread_create(&a_thread, NULL, thread_function, (void *)message);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
printf("Waiting for thread to finish...\n");
res = pthread_join(a_thread, &thread_result);
if (res != 0) {
perror("Thread join failed");
exit(EXIT_FAILURE);
}
printf("Thread joined, it returned %s\n", (char *)thread_result);
printf("Message is now %s\n", message);
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg) {
printf("thread_function is running. Argument was %s\n", (char *)arg);
sleep(3);
strcpy(message, "Bye!");
pthread_exit("Thank you for the CPU time");
}
和第一个程序的编译方法是一样的
这个程序中主线程在创建了新的线程以后会在执行到res = pthread_join(a_thread, &thread_result);并处理机挂起,然后等待新的线程执行结束才会继续向下执行。而且在这个程序中体现了创建线程的一个特点,就是一个进程中的所以的线程都会共享全局变量的,因此在这里message在新的线程中被修改了以后在主线程中的message变量的值也做了相应的改变。