linux c编程:线程创建
前面章节中介绍了进程。从这一章开始介绍线程。进程和线程的差别是什么呢:
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
1) 简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
2) 线程的划分尺度小于进程,使得多线程程序的并发性高。
3) 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
4) 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
5) 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
4.优缺点
线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。
用一个比喻来形容进程和线程。一个工厂里面是由多个车间组成。进程就好比工厂的车间。它代表CPU所能处理的单个任务。但是一个车间里可以有多个工人,他们协同完成车间里面的任务。这些工人就可以看做是线程。因此一个进程里面可以包含多个线程。
车间里面的空间都是工人们共享的,这就代表一个进程的内存空间是共享的。每个线程都可以使用这些共享内存。
但是有可能车间里的某个房间空间有限,只能容纳一个人,比如厕所,里面有人的时候其他人就不能进去,这就代表线程使用某些共享内存的时候,其他线程必须等它结束才能使用这块内存。
为了防止其他人进入房间,就是在房间上加一把锁,先到的人锁上门,后到的人看到上锁,就在门口排队。等锁打开再进去,这就是互斥锁,防止多个线程同时读写某一个块内存区域。
还有些房间可以容纳n个人,如果人数大于n,多出来的人只能在外面等着,就好比某些内存只能给固定数目的线程使用。解决的办法就是在门口挂n把钥匙,进入的人取一把钥匙,出来的时候再把钥匙挂回原处。后到的人发现钥匙架空了就知道必须在门口排队等待。这种做法就叫做信号量。用来保证多个线程不会互相冲突。
下面来看下线程的具体用法:
就像每个进程有一个进程ID一样,每个线程也有一个线程ID。和进程ID在整个系统中是唯一的不同,线程ID只有在它所属的进程上下文中才有意义
线程可以通过pthread_self函数来获得自身的线程ID
#include <pthread.h>
pthread_t pthread_self(void);
当一个程序启动时,就有一个进程被操作系统创建,与此同时一个线程也立刻运行,这个线程就是程序的主线程。如果需要再创建子线程,那么创建的线程就是这个主线程的子线程。主线程把新的作业放到一个工作队列中,主线程不允许每个线程任意处理从队列顶端取出的作业,而是由主线程控制作业的分配。
线程创建:
#include <pthread.h>
pthread_t pthread_create(pthread_t
*restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *),void
*restrict arg);
start_rtn: 新创建的线程从start_rtn函数的地址开始运行,该函数只有一个无类型指针参数arg。如果需要向start_rtn函数传递的参数有一个以上,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为art参数传入
来看一个实际的代码:
#include <stdio.h>
#include <stdlib.h>
#include "func.h"
#include <pthread.h>
#include <unistd.h>
#include <windows.h>
void printids(const char *s){
pid_t pid;
pthread_t tid;
pid=getpid();
tid=pthread_self();
printf("%s pid %lu tid %lu (0x%lx)\n",s,(unsigned
long)pid,(unsigned long)tid,(unsigned long)tid);
}
void *thr_fn(void *arg){
printids("new thread:");
return((void *)0);
}
pthread_t ntid;
int main()
{
int err;
err=pthread_create(&ntid,NULL,thr_fn,NULL);
printids("main thread:");
Sleep(1);
return 0;
}
运行如下:可以看到两个线程的PID都是一样的,不同的是tid
那么线程什么时候退出呢,单个线程有3种方式退出,因此可以在不终止整个进程的情况下,停止它的控制流
1 线程可以简单地从启动例程中返回,返回值是线程的退出码
2 线程可以被同一进程的其他线程取消
3 线程调用pthread_exit
来看下进程中的其他线程如何来取消线程,这就需要用到pthread_join(pthread_t thread, void **rval_ptr)
运行后调用线程一直阻塞,直到指定的线程调用pthread_exit, 退出或者返回
#include <stdio.h>
#include <stdlib.h>
#include "func.h"
#include <pthread.h>
#include <unistd.h>
#include <windows.h>
void *thr_fn2(void *arg){
printf("thread2 exiting\n");
return((void *)2);
}
void *thr_fn1(void *arg){
printf("thread1 returning\n");
return((void *)1);
}
int main()
{
pthread_t tid1,tid2;
void *tret;
pthread_create(&tid1,NULL,thr_fn1,NULL);
pthread_create(&tid2,NULL,thr_fn2,NULL);
pthread_join(tid1,&tret);
printf("thread1 exit code %ld\n",(long)tret);
pthread_join(tid2,&tret);
printf("thread2 exit code %ld\n",(long)tret);
return 0;
}
运行结果:
linux c编程:线程创建的更多相关文章
- Linux多线程编程——线程的创建与退出
POSIX线程标准:该标准定义了创建和操纵线程的一整套API.在类Unix操作系统(Unix.Linux.Mac OS X等)中,都使用Pthreads作为操作系统的线程.Windows操作系统也有其 ...
- Linux系统编程——线程私有数据
在多线程程序中.常常要用全局变量来实现多个函数间的数据共享.因为数据空间是共享的,因此全局变量也为全部线程共同拥有. 測试代码例如以下: #include <stdio.h> #inclu ...
- linux系统编程--线程
安装线程man page,命令:sudo apt-get install manpages-posix-dev 线程概念 什么是线程 LWP:light weight process 轻量级的进程,本 ...
- Unix 环境高级编程---线程创建、同步、
一下代码主要实现了linux下线程创建的基本方法,这些都是使用默认属性的.以后有机会再探讨自定义属性的情况.主要是为了练习三种基本的线程同步方法:互斥.读写锁以及条件变量. #include < ...
- Linux 多线程编程--线程退出
今天分析项目中进程中虚存一直增长问题,运行10个小时虚存涨到121G ,RSS占用为16G 非常恐怖. Valgrind测试无内存泄漏. 内存32G 64bit系统信息如下: Linux线程使用方式是 ...
- Linux多任务编程——线程
线程基础 △ 由于进程的地址空间是私有的,因此在进行上下文切换时,系统开销比较大 △ 在同一个进程中创建的线程共享该进程的地址空间 △ 通常线程值得是共享相同地址空间的多个任务 △ 每个线程的私有这些 ...
- linux系统编程--线程同步
同步概念 所谓同步,即同时起步,协调一致.不同的对象,对“同步”的理解方式略有不同. 如,设备同步,是指在两个设备之间规定一个共同的时间参考: 数据库同步,是指让两个或多个数据库内容保持一致,或者按需 ...
- LInux多线程编程----线程特定数据的处理函数
1.pthread_key_t和pthread_key_create() 线程中特有的线程存储, Thread Specific Data .线程存储有什么用了?他是什么意思了?大家都知道,在多线程程 ...
- Linux系统编程 —线程属性
在之前的章节中,我们在调用pthread_create函数创建线程时,第二个参数(即线程属性)都是设为NULL,即使用默认属性.一般情况下,使用默认属性已经可以解决我们开发过程中的大多数问题. 但是, ...
- Linux系统编程 —线程同步概念
同步概念 同步,指对在一个系统中所发生的事件之间进行协调,在时间上出现一致性与统一化的现象. 但是,对于不同行业,对于同步的理解略有不同.比如:设备同步,是指在两个设备之间规定一个共同的时间参考:数据 ...
随机推荐
- 在web目录下 批量寻找配置文件信息
dir /s /b *.php *.inc *.conf *.config >>list.txt" W4 I2 U+ N/ B6 K @0 r r8 ^ T00LS: _$ j! ...
- Android学习(二十三)SubMenu 子菜单
一.SubMenu子菜单 和功能菜单相似,但是可以添加子菜单. 二.实现步骤: 1.通过onCreateOptionsMenu方法创建子菜单,可以通过代码动态创建,也可以通过xml进行创建. 2.通过 ...
- redis基本数据类型及命令
一.key相关命令 redis本质上是key-value数据库.所以key操作适用于redis的任何数据类型缓存. 1.exists key判断是否存在key,存在返回1,不存在返回0 2.del k ...
- 国内外DNS服务器地址列表大全
DNS(Domain Name System)是域名解析服务器的意思,它在互联网的作用是把域名转换成为网络可以识别的IP地址. 通常来说,香港.韩国.日本等国的DNS服务器速度会比较快,大家可以多用几 ...
- eclispe查看jdk源码后特别卡顿导致未响应解决
第一步:Eclipse -> Preferences -> General -> Startup and Shutdown.不要勾选 RSE UI. 第二步:Eclipse -> ...
- JSON Web Token (JWT) 实现与使用方法
1. JSON Web Token是什么 JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的.自包含的方式,用于作为JSON对象在各方之间安全地传输信息.该 ...
- Ansible@一个高效的配置管理工具--Ansible configure management--翻译(五)
无书面许可请勿转载 高级Playbook Extra variables You may have seen in our template example in the previous chapt ...
- 电路板上为何要有孔洞?何谓PTH/NPTH/vias(导通孔)
推荐文章:PCBA大讲堂:用数据比较OSP及ENIG表面处理电路板的焊接强度 如果你有机会拿起一片电路板,稍微观察一下会发现这电路板上有着许多大大小小的孔洞,把它拿起来对着天花板上的电灯看,还会发 ...
- 捕获网络数据包并进行分析的开源库-WinPcap
什么是WinPcap WinPcap是一个基于Win32平台的,用于捕获网络数据包并进行分析的开源库. 大多数网络应用程序通过被广泛使用的操作系统元件来访问网络,比如sockets. 这是一种简单的 ...
- MyEclipse配置输出控制台信息至文本文件里
有时会遇到这种情况.输出的信息过多,console控制台显示不全然.这是就须要将输出的信息输出到文本文件里,既能够查看也能够备份. 1.右击须要执行的项目->Run As->Run Con ...