嵌入式面试—Liunx常考基础知识(二)—Linux 进程和线程的区别

进程:

进程是程序执行时的一个实例,是担当分配系统资源(CPU时间、内存等)的基本单位。

在面向线程设计的系统中,进程本身不是基本运行单位,而是线程的容器

程序本身只是指令、数据及其组织形式的描述。
进程才是程序(那些指令和数据)的真正运行实例。

典型的UNIX/Linux进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情。
有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程各自处理独立的任务

线程:

线程是操作系统能够进行运算调度的最小单位。

它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。线程包含了表示进程内执行环境必须的信息,其中包括进程中表示线程的线程ID、一组寄存器值、栈、调度优先级和策略、信号屏蔽字、errno常量以及线程私有数据。进程的所有信息对该进程的所有线程都是共享的,包括可执行的程序文本、程序的全局内存和堆内存、栈以及文件描述符。在Unix和类Unix操作系统中线程也被称为轻量级进程(lightweight processes),但轻量级进程更多指的是内核线程(kernel thread),而把用户线程(user thread)称为线程。

进程——资源分配的最小单位,线程——程序执行的最小单位

进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。
线程有自己的堆栈和局部变量,但线程没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。
但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

Linux 进程和线程的相同点

都是实现多任务并发的技术手段,两者都可以独立调度,在多任务环境下,功能上无差异。
二者都是系统独立管理的对象的个体,所以在系统层面都可以实现对二者的控制,并且在多任务程序中,子进程(线程)的调度一般和父进程平等竞争

被问到线程和进程的区别可以从以下几个方面进行回答:

不同点:实现方式,通信方式,控制方式,资源管理等。

1、实现方式:

进程:fork(),将父进程的全部资源复制给了子进程
线程:p_thread_creat,复制了 一小部分必要的资源
补充:

vfork与fork的区别

vfork与fork都可以创建进程,但有两个区别

关键区别一:

vfork直接使用父进程存储空间,不拷贝。

关键区别二:

vfork保证子进程先运行,当子进程调用exit退出后,父进程才执行。

2、通信方式(进程间、线程间)

进程间通信方式有: (八种)

**A. 共享内存 B.消息队列 C.信号量 D.有名管道 E.无名管道 F.信号 G.文件 H.socket **

线程间的通信方式都可以沿用进程间的通信方式(信号除外),并且还有独特 的几种:(十三种)

**A. 互斥量 B.自旋锁 C.条件变量 D.读写锁 E.线程信号 G.全局变量 **

综上:

进程间的通信慢
进程间的通信方式要么需要 使用内核,要么要与外设访问,所以速度比较慢。
线程间的通信快
而线程采用自己特有的通信方式的话,基本都在自己的进程空间内完成,不存在切换,所以通信速度会比较快。
也就是说,线程和进程分别采用的 通信方式,除了种类的区别外还有 速度的区别。
(但是线程也有 内核态线程和 用户态线程)

3、控制方式

进程的 ID 为 pid_t 类型,实际为 一个== int 型的变量。
在全系统中,进程 ID 是唯一标识,对于进程的管理都是通 过 PID 来实现的。每创建一个进程,内核就会去
创建一个结构体来存储该进程的全部信息==。 每一个存储进程的节点都保存自己的 PID,需要管理该进程时就通过这个 ID 来实现,

当子进程结束要收回时,需要调用 wait()系统调用来进行,未回收的 消亡进程会成为僵尸进程,其进程实体已经不存在,但会虚占 PID 资源。

线程的 ID 是一个 Long 型变量, 它的范围大得多,管理方式也不同。
线程 ID 一般在本进程空间内作用就可以了,当然系统在管理线程时也需要记录其信息。 即在内核态创建一个内核态线程与之对应,也就是每一个用户态创建的线程都有 一个内核线程与之对应,但是关系不是一对一,而是多对一,也就是一个内核态 的线程可以对应多个用户级的线程。 想要主动终止线程想要调用 pthread_exit(),主线程需要调用 pthread_join() 来回收。

补充:
僵尸进程:子进程退出状态不被收集,变成僵死进程(僵尸进程),收集退出状态用到的API:wait, waitpid, waitid(wait():如果成功,返回终止子进程的进程ID;错误,返回-1)
孤儿进程:父进程如果不等待子进程退出,在子进程之前就结束了自己的“生命”,此时子进程叫做孤儿进程,Linux避免系统存在过多孤儿进程,==init进程(系统初始化进程,进程ID为1)==收留孤儿进程,变成孤儿进程的父进程

4、资源管理方式

1、进程本身是资源分配的基本单位,因而它的资源都是独立的,如果有多进程间的共享资源,就要用到进程间的通信方式了,比如共享内存。共享数据就放在共享内存去,大家都可以访问,为保证数据写入的安全,加上信号量一同使用。一般而言,共享内存都是和信号量一起使用。消息队列则不同,由于消息的收发是原子操作, 因而自动实现了互斥,单独使用就是安全的。

2、线程间要使用共享资源不需要用共享内存,直接使用全局变量即可,或者 malloc()动态申请内存。显得方便直接。而且互斥使用的是同一进程空间内的互斥量, 所以效率上也有优势。

猜你喜欢

转载自blog.csdn.net/weixin_44933419/article/details/113993018