点击上方 "程序员小乐"关注, 星标或置顶一起成长
每天凌晨00点00分, 第一时间与你相约
每日英文
The moment you think about giving up,think of the reason why you held on so long.
每当你想放弃的时候,想一想是什么支撑着你一路坚持。
每日掏心话
你不知道,我的心情一直被你左右。有时候,躲避是为了让自己不那么失望。
来自:For_zwb | 责编:乐乐
链接:blog.csdn.net/weixin_42250655/article/details/81567643
程序员小乐(ID:study_tech) 第 850 次推文 图源:百度往日回顾:Spring Boot之程序性能监控,看了都说好!
正文
进程
Linux是一个多用户多任务的操作系统。
进程,是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。它的执行需要系统分配资源创建实体之后,才能进行。举个例子:我们所写的程序,在运行的时候它也是一个进程。
进程和程序的区别:程序相当于是一个文件,是有序代码的集合,是静态的存储在硬盘中。而进程是运行中的程序,系统会为变量分配相应的内存和初始化它们的值,还有一些资源如:堆、栈等当程序运行完进程也就结束了,但程序还是保存在硬盘中没有消失。
进程的特性
①并发性:可以与其它进程在宏观上同时向前推进。
②动态性:进程是执行中的程序,动态产生、动态消亡、动态变化。
③独立性:进程是系统资源分配的基本单位。
④交往性:与其它进程可以进行交互。
⑤异步性:不统一推进。
⑥结构性:每个进程有一个控制块PCB。
⑦并行性:只有在多CPU多处理器的计算机上,进程才能并行执行。
我们谈谈并发性和并行性的区别:
并发性是在宏观上的同时向前推进,CPU使用时间轮转机制对进程进行调度,可能一个进程占用CPU短短10ms就切换去执行另一个进程了,而我们的肉眼是不可能看到这种细微的变化,所以我们在宏观概念上认为它是同时推进的,这就是并发性。(一定是在宏观上)
并行性就是真正意义上的一起推进,就是多个进程在同一时间被一起执行。但是上面也提到过,想要支持进程并行,必须是多CPU的计算机。
打个比方理解一下这它们的区别:
现在有一个人吃三个馒头,但是这个人可能比较有意思,他咬一口第一个馒头,迅速的又咬了一口第二个馒头,然后吃了一口第二个馒头可能又去咬了第三个馒头,就这样子他把三个馒头吃完了。这就是并发性。
但是这一边是三个人再吃三个馒头,三个人同时开始吃,然后吃完了三个馒头,这就是并行性。
讲完这些之后,我们再来谈谈在一个进程中如何创建多个进程,并且它们之间又有什么关系呢?
创建进程有两种方式:一种是操作系统创建,另一种是父进程创建。父进程创建的进程(通常称为子进程),它们和父进程存在隶属关系。子进程又可以创建进程,这样形成一个进程家族。子进程可以继承其父进程几乎所有的资源。
父进程创建进程的函数fork: pid_t = fork(void);
pid_t getpid();//进程id
pid_t getppid();//父进程id
pid_t 当调用成功时有两个返回值,一个是父进程调用fork返回值是子进程的id, 第二个是子进程调用fork返回值0。如果创建失败则返回-1。
孤儿进程
孤儿字面意思就是没有父母的孩子,那孤儿进程的意思就是没有父进程的进程。这种情况是怎么发生的呢?就是父进程先于子进程结束,这时子进程被init进程收养,init的进程号为1。
僵尸进程
当一个子进程终止时,如果它的父进程还在运行,内核会为这个终止的子进程保留一定量的信息。父进程可以根据这些信息知道子进程的情况。直到父进程对其进行了善后处理,子进程才会完全终止。在这期间,父进程没有回收子进程并释放子进程占用的资源,这个子进程会成为僵尸进程,它仍然占用一定资源。
进程终止
①从main函数返回 return()。
②调用 exit()。
③调用 _exit()或 _Exit()。
④最后一个线程从其启动例程返回。
⑤最后一个线程调用 pthread_exit()。
⑥调用 abort()它产生 SIGABRT 信号。
⑦收到一个信号并终止。
⑧最后一个线程对取消请求作出相应。
进程组
每个进程都属于某个进程组。进程组是一个或多个进程的集合。通常它们与同一作业相关联,可以接收来自同一终端的各种信号。每个进程组有一个唯一的进程组ID。每个进程组都有一个组长进程,进程ID等于进程组ID的进程就是组长进程。
会话
会话(session)是一个或多个进程组的集合。
竞态条件
当多个进程都企图对共享数据进行某种处理时,而最后的结果又取决于进程运行的顺序时,我们认为发生了竞态条件(race condition)。如果fork之后的某种逻辑显式或隐式地依赖于在fork之后是父进程先运行还是子进程先运行,那么fork函数就会是竞争条件活跃的滋生地。通常,我们都是不可以预估子进程和父进程哪个先运行。因为进程的运行顺序完全取决于内核的调度算法和系统的负载。
我们可以调用wait或者waitpid函数来让父进程等待子进程运行完之后在运行,这样父进程就会被阻塞住,直到子进程运行完毕之后才能运行,其实这样做的效率就比较低,我们fork就是希望多进程并发的执行,如果采用此方法,则fork也就失去了很大的意义。
为了避免竞争条件和不采用wait或waitpid方法,我们可以在多进程之间采用发送和接收信号的处理方法来避免竞态条件。或者各种进程间的通信方式(IPC)也可以使用。
欢迎在留言区留下你的观点,一起讨论提高。如果今天的文章让你有新的启发,学习能力的提升上有新的认识,欢迎转发分享给更多人。
欢迎各位读者加入订阅号程序员小乐技术群,在后台回复“加群”或者“学习”即可。
猜你还想看
Git 如何优雅地回退代码,用 reset 还是 revert ?
关注订阅号「程序员小乐」,收看更多精彩内容
嘿,你在看吗?