process-thread

一、进程的概念:
执行一个程序所分配的资源的总称,进程是程序的一次执行过程动态的,包括创建、调度、执行和消亡
程序就是我们写好的代码,编译成可执行文件后成为程序,存放在硬盘里面。

但是,当我们点击./a,out去执行的时候,它运行起来:把硬盘程序数据读到内存中,占用的cpu资源。等等运行所要的资源的总称,称为进程。
PCB:进程控制块
我们的进程是由一个一个进程链表的来管理的,这个表叫进程控制块PCB,里面有进程标识pid,进程用户,进程状态,,优先级文件描述符表的信息。通过唯一标识pid号进行管理,这个pid其实和fd文件描述符的用法类似,就是一个结构体下标。

一个进程有四种状态:运行态(正常就是运行态) ,等待态(休眠),停止态()进程被命令中止,僵尸态(进程已经被中止,但是pcb资源没有被回收)

进程创建

#include  <unistd.h>
 pid_t  fork(void);
创建新的进程,失败时返回-1
成功时父进程返回子进程的进程号,子进程返回0
通过fork的返回值区分父进程和子进程

子进程继承了父进程的内容
父子进程有独立的地址空间,互不影响
若父进程先结束
子进程成为孤儿进程,被init进程收养
子进程变成后台进程
若子进程先结束
父进程如果没有及时回收,子进程变成僵尸进程

进程回收:
子进程结束时由父进程回收
孤儿进程由init进程回收
若没有及时回收会出现僵尸进程

回收全部子进程
 #include  <unistd.h>
 pid_t wait(int *status); 
 成功时返回回收的子进程的进程号;失败时返回EOF
 若子进程没有结束,父进程一直阻塞
 若有多个子进程,哪个先结束就先回收
 status 指定保存子进程返回值和结束方式的地址
 status为NULL表示直接释放子进程PCB,不接收返回值
 回收指定进程:
 #include  <unistd.h>
  pid_t waitpid(pid_t pid, int *status, int option);
   
 成功时返回回收的子进程的pid或0;失败时返回EOF
  pid可用于指定回收哪个子进程或任意子进程
 status指定用于保存子进程返回值和结束方式的地址
 option指定回收方式,0 或 WNOHANG

二、线程的概念;
由于进程间通信数据交互非常麻烦且进程开销非常大。所以我们引入了线程的概念。线程是轻量级的进程:
linux其实不区分进程和线程:他们都是一个task_struct链表来管理。
进程右不同的pid号,同一进程下所有线程都共享同一个pid。并且就算你不创建线程,那么进程里面也会有一个线程。就是你一个./a.out这个进程,执行mian函数即是一个进程也是一个线程。多线程下的task_structlm里面的pid号是一样的。

线程的好处:
大大提高了任务切换的效率
避免了额外的TLB & cache的刷新

线程的创建:

#include  <pthread.h>
 int  pthread_create(pthread_t *thread, const
       pthread_attr_t *attr, void *(*routine)(void *), void *arg);

 成功返回0,失败时返回错误码
 thread 线程对象
 attr 线程属性,NULL代表默认属性
 routine 线程执行的函数
 arg 传递给routine的参数 ,参数是void * ,注意传递参数格式,

pthread_t  pthread_self(void)   查看自己的TID

创建一个线程去处理 void *(*routine)(void *)这个函数,处理完毕,线程结束并注销。如果进程结束,那么所有的线程都结束,不管你的程序有没有执行完。一个线程用exit();退出,所有的线程都会退出。exit()直接退出程序。

线程的回收:

#include  <pthread.h>
 int  pthread_join(pthread_t thread, void **retval);
       
 成功返回0,失败时返回错误码
 thread 要回收的线程对象
 调用线程阻塞直到thread结束
 *retval 接收线程thread的返回值

线程的取消:

int pthread_cancel(pthread_t thread);

取消是停止线程但是资源没有释放
线程的结束:

 #include  <pthread.h>
 void  pthread_exit(void *retval);
       
 结束当前线程
 retval可被其他线程通过pthread_join获取
 线程私有资源被释放

——————————————————————————————————————————————
三、线程间的同步和互斥
线程间的同步:
信号量
适用于,当某事件发生后,另一个事件才能发生的情况:例如:
我一个线程要往一个buf里面写数据,我另一个线程要读数据。
肯定要先写才能读数据啊,所以我可以定义一个信号量,起始信号量为0 ,用于信号的同步,当我写好之后我的信号量+1,这样就可以读数据了。读完信号量减一。这样就不能再次读数据了。

信号量操作:

1)初始化信号量:
 #include  <semaphore.h>
 int  sem_init(sem_t *sem, int pshared, unsigned int val);
 成功时返回0,失败时EOF
 sem  指向要初始化的信号量对象
 pshared   0 – 线程间   1 – 进程间
 val  信号量初值

2)信号量的P/V操作:
 #include  <semaphore.h>
 int  sem_wait(sem_t  *sem);       P操作
 int  sem_post(sem_t  *sem);       V操作
 成功时返回0,失败时返回EOF
 sem  指向要操作的信号量对象

线程间的互斥:
锁机制:mutex
适用于:多线程访问共享资源时,对共享资源上锁。让其它线程不可访问。以避免出现数据紊乱的情况。

比如我一个线程在往一个buf里面写数据
我另一个也在往buf里面写数据
因为线程是并行的,这样这个数据你永远都预测不到它长什么样子了
一个线程申请锁后必须释放锁。
要不然共享资源就变成你家的资源了,别人都用不了。

初始化锁:
#include  <pthread.h>
 int  pthread_mutex_init(pthread_mutex_t *mutex,
       const pthread_mutexattr_t *  attr);
 成功时返回0,失败时返回错误码
 mutex  指向要初始化的互斥锁对象
 attr  互斥锁属性,NULL表示缺省属性

2)申请锁
#include  <pthread.h>
 int  pthread_mutex_unlock(pthread_mutex_t *mutex);

 成功时返回0,失败时返回错误码
 mutex  指向要初始化的互斥锁对象
 执行完临界区要及时释放锁

3)释放锁
#include  <pthread.h>
 int  pthread_mutex_unlock(pthread_mutex_t *mutex);

 成功时返回0,失败时返回错误码
 mutex  指向要初始化的互斥锁对象
 执行完临界区要及时释放锁

——————————————————————————————————
多进程与多线程的比较:

进程:
进程有独立的地址空间
Linux为每个进程创建task_struct
每个进程都参与内核调度,互不影响

线程:
进程在切换时系统开销大
很多操作系统引入了轻量级进程LWP
同一进程中的线程共享相同地址空间
Linux不区分进程、线程

多线程共享的资源:
一个进程中的多个线程共享以下资源:
可执行的指令
静态数据
进程中打开的文件描述符
当前工作目录
用户ID
用户组ID

线程间私有的资源:
每个线程私有的资源包括:
线程ID (TID)
PC(程序计数器)和相关寄存器
堆栈
错误号 (errno)
优先级
执行状态和属性

并行和并发的概念
并行是程序在同一时刻一起运行,并发是俩个程序是一个发生的。并发不一定并行:

什么时候适用多进程,什么时候使用多线程:

1、首先你得理解多线程的怎么执行的?它是怎么做到多线程并发的。
这个问题其实,多线程其实是并发的但是不是并行的,根据时间片,一会执行这个线程,一会执行另一个线程。其实他是一个时间处理一条语句,然后时间片轮转着去执行各线程的语句。这比较费时间。
类似于:单核的多进程。
时间片轮询进程调度算法,它的思想简单介绍如下: 在操作系统的管理下,所有正在运行的进程轮流使用CPU,每个进程允许占用CPU的时间非常短(比如10毫秒),这样用户根本感觉不出来CPU是在轮流为多个进程服务,就好象所有的进程都在不间断地运行一样。但实际上在任何一个时间内有且仅有一个进程占有CPU及CPU的运算器。
在多核的情况下多线程也可以实现并行。

2多进程的实现:
要是你的进程数小于cpu的核数。比如我exynos4412这个板子是4核的,买手机的时候会看的参数就是什么四核,八核。就是cpu的个数。要是你的进程数小于cpu的核数。那么你的进程就可以做到真正的并发。就是在同一时间片下,会有1,2,3,4等进程同时执行程序的可能。要是进程数大于ccpu核数,那么也将采用 ——时间片轮询进程调度算法。不过有四各时间片可以调度。

结合上面的多进程多线程的实现,以及线程核进程的特性:

如果你想要少消耗资源:多线程

如果你两个程序要频繁交互数据:多线程

如果你想要两程序间数据少交互为了安全:多进程

如果你要处理很多数据,程序要做的事情很多,其实进程的运算速度就比线程要快。毕竟资源更多。
但是简单的程序线程更快不用申请资源。

选择多进程核多线程要更据实际来选。要求的运算熟度,和内存空间。

我们可以利用:time ./生成的可执行文件看它的运行时间。

详细的可以看这个博主写的,挺详细的…这个可以点…

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值