进程,线程,孤儿进程,僵尸进程。

进程和线程

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

进程: 线程+内存+文件/网络句柄

  • “内存”:

我们通常所理解的内存是我们所见到的(2G/4G/8G/16G)物理内存,它为什么会在进程之中呢?
实际上,这里的内存是逻辑内存。指的是内存的寻址空间。每个进程的内存是相互独立的。
否则的话会出现一个问题:我们把指针的值改一改就指向其他进程的内存了,通过这样我们岂不是就可以看到其他进程中"微信"或者是"网上银行"的信息,
这样的话,那我们的微信聊天记录或者是银行账户的信息就都被别人找到了,这是一个很危险的信号!显然这样是不可能的。

  • “文件/网络句柄”:
    它们是所有的进程所共有的,例如打开同一个文件,去抢同一个网络的端口这样的操作是被允许的。

  • “线程”:
    接下来,我们就要介绍一下我们的“线程”有关知识
    在这里插入图片描述

线程

线程:线程(栈+PC+TLS)

  • 栈:
    我们通常都是说调用堆栈,其实这里的堆是没有含义的,调用堆栈就是调用栈的意思。
    那么我们的栈里面有什么呢?
    我们从主线程的入口main函数,会不断的进行函数调用,
    每次调用的时候,会把所有的参数和返回地址压入到栈中。

  • PC:
    Program Counter 程序计数器,操作系统真正运行的是一个个的线程,
    而我们的进程只是它的一个容器。PC就是指向当前的指令,而这个指令是放在内存中。
    每个线程都有一串自己的指针,去指向自己当前所在内存的指针。
    计算机绝大部分是存储程序性的,说的就是我们的数据和程序是存储在同一片内存里的
    这个内存中既有我们的数据变量又有我们的程序。所以我们的PC指针就是指向我们的内存的。

    注:缓冲区溢出
    例如我们经常听到一个漏洞:缓冲区溢出
    这是什么意思呢?
    例如:我们有个地方要输入用户名,本来是用来存数据的地方。
    然后黑客把数据输入的特别长。这个长度超出了我们给数据存储的内存区,这时候跑到了
    我们给程序分配的一部分内存中。黑客就可以通过这种办法将他所要运行的代码
    写入到用户名框中,来植入进来。我们的解决方法就是,用用户名的长度来限制不要超过
    用户名的缓冲区的大小来解决。

  • TLS:
    全称:thread local storage
    之前我们看到每个进程都有自己独立的内存,这时候我们想,我们的线程有没有一块独立的内存呢?答案是有的,就是TLS。
    可以用来存储我们线程所独有的数据。
    可以看到:线程才是我们操作系统所真正去运行的,而进程呢,则是像容器一样他把需要的一些东西放在了一起,而把不需要的东西做了一层隔离,进行隔离开来。

进程之间的是怎么进行交互的呢?

通过TCP/IP的端口来实现

线程之间又是怎样进行交互?

线程的通信就比较简单,有一大块共享的内存,只要大家的指针是同一个就可以看到各自的内存。

小结
1.进程要分配一大部分的内存,而线程只需要分配一部分栈就可以了.
2.一个程序至少有一个进程,一个进程至少有一个线程.
3.进程是资源分配的最小单位,线程是程序执行的最小单位。
4.一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行.

僵尸进程和孤儿进程

僵尸进程:僵尸进程是当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。
孤儿进程:孤儿进程则是指当一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

僵尸进程和孤儿进程的区别:

区别:僵尸进程将会导致资源浪费,而孤儿进程则不会。
僵尸进程的危害:
系统所能使用的进程号是有限的,如果大量差生僵尸进程,将因为没有可用的进程号,导致无法产生新的进程,这就是僵尸进程的危害。孤儿进程是没有父进程,init 进程充当父进程,因此孤儿进程并没有什么危害。

init进程

https://blog.51cto.com/13438667/2105458

进程之间的通信

  1. 管道: mkfifo 管道的通知机制类似于缓存,就像一个进程把数据放在某个缓存区域,然后等着另外一个进程去拿,并且是管道是单向传输的。通信方式效率低下,你看,a 进程给 b 进程传输数据,只能等待 b 进程取了数据之后 a 进程才能返回。
  2. 消息队列: 可以把进程的数据放在某个内存之后就马上让进程返回,无需再等待其他进程取了数据再返回。缺点:如果a 进程发送的数据占的内存比较大,并且两个进程之间的通信特别频繁的话,消息队列模型就不大适合了。因为 a 发送的数据很大的话,意味**发送消息(拷贝)**这个过程需要花很多时间来读内存
  3. 共享内存:系统加载一个进程的时候,分配给进程的内存并不是实际物理内存,而是虚拟内存空间。那么我们可以让两个进程各自拿出一块虚拟地址空间来,然后映射到相同的物理内存中,这样,两个进程虽然有着独立的虚拟内存空间,但有一部分却是映射到相同的物理内存,这就完成了内存共享机制了。
  4. 信号量:信号量的本质就是一个计数器,用来实现进程之间的互斥与同步。例如信号量的初始值是 1,然后 a 进程来访问内存1的时候,我们就把信号量的值设为 0,然后进程b 也要来访问内存1的时候,看到信号量的值为 0 就知道已经有进程在访问内存1了,这个时候进程 b 就会访问不了内存1。所以说,信号量也是进程之间的一种通信方式。
  5. Socket:用于多个进程再不同主机中通信。例如 http请求就是 socket通信

线程之间的通信:

线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。

  1. 锁机制:包括互斥锁、条件变量、读写锁和自旋锁。

    互斥锁确保同一时间只能有一个线程访问共享资源。当锁被占用时试图对其加锁的线程都进入阻塞状态(释放CPU资源使其由运行状态进入等待状态)。当锁释放时哪个等待线程能获得该锁取决于内核的调度。

    读写锁当以写模式加锁而处于写状态时任何试图加锁的线程(不论是读或写)都阻塞,当以读状态模式加锁而处于读状态时“读”线程不阻塞,“写”线程阻塞。读模式共享,写模式互斥。

    条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。

    自旋锁上锁受阻时线程不阻塞而是在循环中轮询查看能否获得该锁,没有线程的切换因而没有切换开销,不过对CPU的霸占会导致CPU资源的浪费。 所以自旋锁适用于并行结构(多个处理器)或者适用于锁被持有时间短而不希望在线程切换产生开销的情况。

  2. 信号量机制(Semaphore):包括无名线程信号量和命名线程信号量

  3. 信号机制(Signal):类似进程间的信号处理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值