在linux内核,线程与进程的区别很小,或者说内核并没有真正所谓单独的线程的概念,进程的创建函数是fork,而线程的创建是通过clone实现的。

而clone与fork都是调用do_fork(),差异如下:

 SYSCALL_DEFINE0(fork)
{
return do_fork(SIGCHLD, , , NULL, NULL);
} SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
int __user *, parent_tidptr,
int __user *, child_tidptr,
int, tls_val)
{
return do_fork(clone_flags, newsp, , parent_tidptr, child_tidptr);
}

实际上就是内核开放大部分参数和do_fork接口来创建线程,看clone的官方解释:

The main use of clone() is to implement threads: multiple threads of control in a program that run concurrently in a shared memory space.

所以接下来参考glibc 2.25版本的pthread_create来看看进程和线程的具体实现差异在哪里:

 const int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SYSVSEM
| CLONE_SIGHAND | CLONE_THREAD
| CLONE_SETTLS | CLONE_PARENT_SETTID
| CLONE_CHILD_CLEARTID
| );

显而易见clone_flags的差别非常大.

下面再来通过这些flags的作用来区分进程和线程的特性,细数之前先看看do_fork的实现,发现有意思的是,ptrace和perf这2个调试工具也是进程创建的时候初始化的.

1、CLONE_VM

首先线程不能脱离父进程独立存在,所以它需要共享父进程的虚拟内存空间

2、CLONE_FS | CLONE_FILES

线程做为父进程一个CPU执行单元,它可以直接使用父进程的文件系统信息(包括文件系统根目录,当前工作目录,和文件访问权限)而不需要自己独立创建和持有这些资源和父进程打开的文件描述符

3、CLONE_SIGHAND | CLONE_THREAD

线程还接着共享父进程的异步信号处理函数,即父进程能收到的异步信号,它也能收到并处理,不过线程可以自行通过sigprocmask来屏蔽或不屏蔽某些异步信号操作,而不影响其他线程。

4、CLONE_SYSVSEM

线程共享父进程的System V semaphore。

5、CLONE_SETTLS

线程支持TLS (Thread Local Storage)。TLS使得变量每一个线程有一份独立实体,各个线程的值互不干扰

6、CLONE_PARENT_SETTID

父进程和线程会将线程ID保存在内核任务结构体的ptid成员。

7、CLONE_CHILD_CLEARTID

清除内核任务结构体的ctid成员上存储的线程ID。

8、CLONE_THREAD

将线程放入到父进程的线程组(thread group)里,这样线程在用户态就看不到自己进程ID了,只能看到父进程的进程ID,并且线程共享父进程的异步信号。

子进程则会复制父进程的很多进程信息,复制与共享的区别还是很大的,复制需要重新申请内核资源,所以开销比线程大很多。

1、创建进程的时候没有指定 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,所以这些它需要复制进程的,所以父进程这些信息也被子进程继承过去了,但是已经独立存在在子进程里了,以后就没有关系了。

2、子进程还复制父进程的信号处理函数和信号;

3、线程和子进程都会继承(复制)父进程的普通优先级,父进程的栈,CPU状态会被设置为RUNNING。

总结一下:

1、进程,线程的创建还有很多细节,我这里没有完全列举出来,只列举了我觉得比较重要的部分。

2、线程,进程的最大区别就是,啃老还是不啃老,通过上面来看,线程就是个啃老的货,而进程是个依靠父母独立成长的好孩子,然并卵,事实证明,不管是现实世界还是计算机这个虚拟世界,越独立就越占用资源!

4、所以,多用线程可以降低系统资源的消耗。

上面讲到要多用线程,下面就轮到线程池要出场了,但是这个世界总是有很多熊孩子,就喜欢不停给他老子搞事情,严重到。。。咳咳,我们还是严肃的描述吧:

严重到不停的创建线程,销毁线程,这就增加了内核的开销了,更有甚之,有的线程函数无比简短,可能线程刚创建完就要销毁了。。。

所以避免出现这样的情况,很多场合需要用到进程池。

关于pthread可以参考如下文章:

http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part1/

https://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part2/

https://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part3/

https://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part4/

https://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part5/

Linux 进程,线程,线程池的更多相关文章

  1. Linux进程或线程绑定到CPU

    Linux进程或线程绑定到CPU 为了让程序拥有更好的性能,有时候需要将进程或线程绑定到特定的CPU,这样可以减少调度的开销和保护关键进程或线程. 进程绑定到CPU Linux提供一个接口,可以将进程 ...

  2. Linux进程和线程的比較

    进程与线程 參考:http://www.cnblogs.com/blueclue/archive/2010/07/16/1778855.html 首先比較Linux进程和线程的创建的差别,以此展开: ...

  3. Linux 进程、线程运行在指定CPU核上

    /******************************************************************************** * Linux 进程.线程运行在指定 ...

  4. Linux进程与线程的区别

    进程与线程的区别,早已经成为了经典问题.自线程概念诞生起,关于这个问题的讨论就没有停止过.无论是初级程序员,还是资深专家,都应该考虑过这个问题,只是层次角度不同罢了.一般程序员而言,搞清楚二者的概念, ...

  5. linux进程、线程与cpu的亲和性(affinity)

    参考:http://www.cnblogs.com/wenqiang/p/6049978.html 最近的工作中对性能的要求比较高,下面简单做一下总结: 一.什么是cpu亲和性(affinity) C ...

  6. linux进程与线程的区别【转】

    知乎上总结: "linux使用的1:1的线程模型,在内核中是不区分线程和进程的,都是可运行的任务而已.fork调用clone(最少的共享),pthread_create也是调用clone(最 ...

  7. Linux进程和线程

    一.进程产生的方式 1.描述进程的ID号通常叫做PID,即进程ID,PID的变量类型为pid_t. 2.getpid(void)返回当前进程的ID号,getppid(void)返回当前进程的父进程的I ...

  8. Linux -- 进程或线程独占CPU

    如果想让特定进程或线程独占某一或某些CPU,我们需要做三件事. 一,隔离CPU,避免其它线程run在被隔离的CPU上. 二,绑定所有的interrupts到非隔离的CPU上,避免被隔离的CPU收到in ...

  9. 操作系统:Linux进程与线程

    这里是一部分内容,还会做修改. 一:目的及内容 学习fork(),exec,pthread库函数的使用,阅读源码,分析fork,exec,pthread_create函数的机理 代码实现: 进程A创建 ...

  10. Linux 进程与线程

    进程与线程   进程 进程就是在操作系统中运行的程序,是操作系统资源管理的最小单位.一个进程可以管理多个线程,线程相对轻量,可以共享进程地址空间 线程来源 一个进行在运行的过程中,不可能一直占据着CP ...

随机推荐

  1. java之递归学习

    递归思想(2018-10-22): 递归就是方法里调用自身 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口 递归算法代码显得很简洁,但递归算法解题的运行效率较低.所以不提倡用递归设计程序 ...

  2. nginx配置、域名、前端代码部署

    服务器上部署nginx,部署多个独立的代码,用nginx做域名映射的配置方法: 修改/usr/local/nginx/conf/nginx.conf文件,重点是最后一行,include /data/n ...

  3. Linux 安装 python 指定版本--编译源码方式

    自动化脚本: #!/bin/bash sudo apt-get update sudo apt-get install -y gcc make build-essential libssl-dev z ...

  4. Java分享笔记:Java网络编程--TCP程序设计

    [1] TCP编程的主要步骤 客户端(client): 1.创建Socket对象,构造方法的形参列表中需要InetAddress类对象和int型值,用来指明对方的IP地址和端口号. 2.通过Socke ...

  5. Linux性能监控工具 gtop

    给大家介绍一款性能监控工具,个人对比界面比top美观,常用指标比较清晰毕竟top上的指标不是每个人都能熟悉,也不是所有指标参数都需要看,对于新手也不便查找,好了说的再多先上图大家参观一下. 1.安装需 ...

  6. deepin系统无线网络卡死或者极慢的解决方案

    在初次安装deb或者fedara系列的桌面发行版的之后,经常会出现无线网络极慢甚至卡死的状况. 笔者在初次使用deepin系统的时候,也遇到同样的问题,很大程度上是由于没有安装对应的驱动. 下面给出对 ...

  7. QQ群技术:0成本创建2000人QQ群技巧

    群人数,直接关系群权重;于排名,意义非凡;此法靠谱,笔者亲测. 就说这张图,这类关键词,要是没2000人群,不管你多流弊,你是做不上去滴. 于QQ群霸屏,笔者有太多的笔墨,各种排名技巧,阿力推推早前明 ...

  8. laravel 中出现SQLSTATE[HY000] [2002] 如何解决?

    在日常开发中总是难免遇到各式各样的错误,还有许多错误常常是重复出现的 以下是报错信息! SQLSTATE[HY000] [2002] ������ӷ���һ��ʱ���û���ȷ�

  9. js onsubmit和return false的关系

    一直以来,我都是以为onsubmit=“return false”就不会进行提交,但经过项目之后才知道return false只是避免了之后的跳转,但onsubmit已经是正在进行了,故onsubmi ...

  10. Delphi方法重载

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...