您的位置:首页 > 运维架构 > Linux

Linux之线程:控制与分离

2016-09-26 18:05 141 查看
  之前我一直都提到的是进程,现在多了一个线程的概念,从字面意思来看,线程应该比进程小。嘿嘿。
 其实操作系统刚开始的时候,提出进程概念后,操作系统一直都是以进程作为独立运行的基本单位,然后有人感觉了,这不对呀,进程之间的中断转换太浪费了,并且用户态到核心态的切换也有点麻烦,所以在80年代中期,人们又提出了毕竟更小的独立运行的基本单位咯--线程,用来提高系统内存程序的并发执行程度。所以线程就这么出现了。
 那,什么是线程呢?
    其实简单来说,线程就是进程中的执行分流,从操作系统内部来说其实就是一个指令序列,他执行了地址上的跳转,但是却不影响其他流程的执行。进程它所针对的是独占我们所有的资源,但是线程确实在单个进程之下进行资源的共享,但是共享虽然共享,但是人嘛,不管怎么过度曝光,都有着自己的隐私,所以我们看一下线程所需要拥有的属性:
       由于同一进程的多个线程共享同一地址空间,因此Text Segment、Data Segment都是共享的,如果定义一个函数,在各线程中都可以调用,如果定义一 个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境:1. 文件描述符表2. 每种信号的处理方式(SIG_IGN、SIG_DFL或者自定义的信号处理函数)3. 当前工作目录4. 用户id和组id但有些资源是每个线程各有一份的:1. 线程id2. 上下文,包括各种寄存器的值、程序计数器和栈指针3. 栈空间4. errno变量5. 信号屏蔽字6. 调度优先级    以上是关于线程的概念,以后我会提到用户态线程与核心态线程,这里暂且不提,我们来看一下如何在Linux下使用线程。

下面来讲解一下线程控制:  首先要注意一点的是,之前提到的进程都是system V版本的系统,所以他的库调用都是   #include<sys/XXX>但是关于线程,我们遵循的是POSIX版本的系统,一定要注意这一点。

然后看一下线程的创建函数:注意在编译包含使用线程的程序是,需要在gcc命令后面加上-lpthread

返回值有问题,我也不知道为什么。。。
其中需要注意点,当创建一个线程,并且在join等待一个线程时,需要当前的逻辑流执行完以后才能执行下面的代码,也就是为什么3个线程的ID是相同的了。

    有关分离线程
    在任何一个时间点上,线程是可结合的(joinable)或者是分离的(detached)。一个可结合的线程能够被其他线程收回其资源和杀死。在被其他线程回收之前,它的存储器资源(例如栈)是不释放的。相反,一个分离的线程是不能被其他线程回收或杀死的,它的存储器 资源在它终止时由系统自动释放。默认情况下,线程被创建成可结合的。为了避免存储器泄漏,每个可结合线程都应该要么被显示地回收,即调用pthread_join;要么通过调用pthread_detach函数被分离。
    如果一个可结合线程结束运行但没有被joi
aaad
n,则它的状态类似于进程中的Zombie Process,即还有一部分资源没有被回收,所以创建线程者应该调用pthread_join来等待线程运行结束,并可得到线程的退出代码,回收其资源。由于调用pthread_join后,如果该线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此。例如,在Web服务器中当主线程为每个新来的连接请求创建一个子线程进行处理的时候,主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的连接请求),这时可以在子线程中加入代码
pthread_detach(pthread_self())
或者父线程调用
pthread_detach(thread_id)(非阻塞,可立即返回)
这将该子线程的状态设置为分离的(detached),如此一来,该线程运行结束后会自动释放所有资源。
代码如下:#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *thread_run(void *_val)
{
pthread_detach(pthread_self());
printf("%s\n",(char *)_val);
return NULL;
}

int main()
{
pthread_t tid;
int tret = pthread_create(&tid,NULL,thread_run,"thread1 run...");
if(tret != 0)
{
printf("create thread error,info is :%s\n",strerror(tret));
return tret;
}
int ret = 0;
sleep(1);
if(0 == pthread_join(tid,NULL))
{
printf("wait 1");
ret = 0;
}
else{
printf("wait failed");
ret = 1;
}
return ret;
}
运行结果:




好了,总结一下:
    其实关于线程,我们在理解他的出现由来和基本概念之后我们知道为什么需要他的存在,例如我们加载一个网页,图片,视频,还有文字是分别加载的,如果用单进程进行加载的话他们是交错出现,但是如果使用多线程的话他们可以同时进行加载,并且也比进程快,所以线程的出现解决了模块问题的并发或者单列处理。
    然后就是关于Linux系统下的线程编程了,其实只要理解线程的创建,等待,分离,终止,就可以算作是我们能够操纵进程了,记住他的几个相关操作函数,就OK了,其实线程就是进程的肢体而已。

以上。

本文出自 “剩蛋君” 博客,请务必保留此出处http://memory73.blog.51cto.com/10530560/1765384
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: