三、linux最小资源单位。 -- 线程。
1、 进程与线程的区别?
linux --- 社会
进程 --- 人
线程 --- 人的手
线程是一个进程的内部资源。
2、如何开启一个进程? 如何开启一个线程?
./xxxx -> 开启一个进程
xxxx.c
int main(int argc,char *argv[])
{
/* 代表进程的开始 */
xxxx;
/* 进程的运行过程 */
---> 可以使用函数创建很多个线程。
/* 代表进程的结束,就会导致这个进程内部的所有线程都退出 */
return 0;
}
四、线程的函数接口?
线程中所有函数接口都是在线程库中,所以都是查看man手册的第3手册。
1、 如何创建一个子线程? -> pthread_create() -> man 3 pthread_create
功能: create a new thread
//创建一个子线程
头文件:
#include <pthread.h>
原型:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
参数:
thread:存放线程ID号的变量的地址。
attr:线程的属性 普通属性 -> NULL
start_routine:线程的例程函数(子线程需要做的事情,把这些事情放在一个函数中即可,函数必须长:void *fun(void *arg)) arg:传递给子线程例程函数的参数,如果不需要传递,则填NULL。
返回值:
成功:0
失败:非0
注意:
Compile and link with -pthread.
//如果你使用了该函数,则编译时必须链接线程库。
本来: gcc xxx.c -o xxx
现在: gcc xxx.c -o xxx -lpthread
gec@ubuntu:/mnt/hgfs/GZ2057/09 系统编程/05/code$ gcc pthread_create.c -o pthread_create
/tmp/ccl10xXX.o: In function `main':
pthread_create.c:(.text+0x75): undefined reference to `pthread_create' -> 没有链接线程库
collect2: error: ld returned 1 exit status
2、 案例
尝试在进程中创建一个子线程,让主线程做一件事情,让子线程也去做一件事情,看看会不会同时做。
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
//子线程
void *my_fun(void *arg)
{
//4. 子线程每隔2S打印一句话appletree,一共打印6S。
int i;
for(i=0;i<3;i++)
{
printf("appletree!\n");
sleep(2);
}
}
int main(int argc,char *argv[])
{
//1. 现在还是一个单进程的程序。
printf("singal process!\n");
//2. 创建一个子线程。
// 本来的进程叫做主线程。
pthread_t tid;
pthread_create(&tid,NULL,my_fun,NULL);
//3. 主线程每隔1S打印一句话helloworld,一共打印10S。
int i;
for(i=0;i<10;i++)
{
printf("helloworld!\n");
sleep(1);
}
return 0; //进程退出,都会导致这个进程中所有的线程都会退出。
}
3、 接合线程。 -> pthread_join() -> man 3 pthread_join
功能: pthread_join - join with a terminated thread
//接合一个结束的线程。
头文件:
#include <pthread.h>
原型:
int pthread_join(pthread_t thread, void **retval);
参数:
thread: 需要接合的线程的ID号。
retval: 子线程的退出值,如果不关心,则填NULL。
返回值:
成功:0
失败:非0
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
//子线程
void *my_fun(void *arg) //arg = (void *)&a
{
printf("a = %d\n",*(int *)arg);
//4. 子线程每隔2S打印一句话appletree,一共打印6S。
int i;
for(i=0;i<10;i++) // 10S
{
printf("helloworld!\n");
sleep(1);
}
}
int main(int argc,char *argv[])
{
//1. 现在还是一个单进程的程序。
printf("singal process!\n");
//2. 创建一个子线程。
// 本来的进程叫做主线程。
pthread_t tid;
int a = 100;
pthread_create(&tid,NULL,my_fun,(void *)&a);
//3. 主线程每隔1S打印一句话helloworld,一共打印10S。
int i;
for(i=0;i<3;i++) //6S
{
printf("appletree!\n");
sleep(2);
}
//4. 接合线程
pthread_join(tid,NULL); //等待子线程退出了,这个函数才返回!
return 0; //进程退出,都会导致这个进程中所有的线程都会退出。
}
一、主线程如何知道子线程怎么退出的?
//子线程
void *fun(void *arg)
{
}
pthread_join(tid,NULL); -> 只等待子线程,但是不关心子线程的退出值。
pthread_join(tid,不为NULL); -> 除了会等到子线程,还会接收子线程退出值。 -> 但是子线程要主动返回它自己的退出值。
二、子线程如何退出的?如何返回退出值? -> pthread_exit() -> man 3 pthread_exit
1、 函数功能:
功能: pthread_exit - terminate calling thread
//结束一个正在运行的线程
头文件:
#include <pthread.h>
原型:
void pthread_exit(void *retval);
参数:
retval:退出值的地址 -> 不能是局部变量,只能是全局
返回值:无
//子线程的退出值不能是局部变量
//因为:
int state1 = 20; -> 全局不会释放。
void *fun(void *arg)
{
int state2 = 10; //局部变量 ->局部变量的空间会释放。
pthread_exit(&state1);
}
2、 子线程退出与主线程接合结合一起使用。
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
int state = 9; //子线程的退出值
void *fun(void *arg)
{
//子线程工作内容
int i;
for(i=0;i<5;i++)
{
printf("helloworld!\n");
sleep(1);
}
//2. 子线程主动返回退出值。
pthread_exit((void *)&state);
}
int main(int argc,char *argv[])
{
//1. 直接创建一个子线程
pthread_t tid;
pthread_create(&tid,NULL,fun,NULL);
//3. 主动接合线程,并且接收子线程的退出值。
void *p = NULL;
pthread_join(tid,&p); -> p就是指向子线程的退出值。
int ret_value = *(int*)p;
printf("exit_state = %d\n",ret_value);
if(ret_value == 10) //如果等于10,就代表主线程知道子线程是正常退出的
{
printf("ok!\n");
}
else{ //异常退出
printf("error!\n");
}
}
三、导致线程退出的几种情况。
The new thread terminates in one of the following ways:
以下的情况的其中一种都会导致线程的退出。
* It calls pthread_exit(3), specifying an exit status value that is available to another thread in the same process that calls pthread_join(3).
//当线程调用pthread_exit()函数可以导致退出,还可以将退出值返回给那个接合它的线程。
* It returns from start_routine(). This is equivalent to calling pthread_exit(3) with the value supplied in the return statement.
//例程函数返回也会导致退出,return后面可以跟着退出值,这种等价于使用pthread_exit()
* It is canceled (see pthread_cancel(3)).
//线程被取消了,也会导致线程退出。
* Any of the threads in the process calls exit(3), or the main thread performs a return from main(). This causes the termination of all threads in the process.
在进程中的任意一个线程调用exit(),或者主线程的main函数返回了(进程的退出),都会导致整个进程中所有的线程退出。