Linux进程和线程的区别

我们知道一个程序是计算机若干指令顺序执行的集合,在单进程且单线程的程序中,所有指令从头到尾线性执行,没有并发性,但是在引入多线程之后,同一个进程中的指令可以并发执行,这就是多线程的基本思想.

1.进程和线程的创建方式:

首先看看线程创建函数:

线程创建函数:
pthread_create函数
    原型:int  pthread_create((pthread_t  *thread,  pthread_attr_t  *attr,  void  *(*start_routine)(void  *),  void  *arg)
    用法:#include  <pthread.h>
    功能:创建线程(实际上就是确定调用该线程函数的入口点),在线程创建以后,就开始运行相关的线程函数。
    说明:thread:线程标识符;
              attr:线程属性设置;
              start_routine:线程函数的起始地址;
              arg:传递给start_routine的参数;
              返回值:成功,返回0;出错,返回-1。
进程创建函数:

进程的创建函数:头文件 #include<unistd.h>
第一种: pid_t fork(void)
返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1
一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。
第二种: pid_t vfork(void);
fork与vfork的区别
1. fork要拷贝父进程的数据段;而vfork则不需要完全拷贝父进程的数据段,在子进程没有调用exec和exit之前,子进程与父进程共享数据段.
2. fork不对父子进程的执行次序进行任何限制;而在vfork调用中,子进程先运行,父进程挂起,直到子进程调用了exec或exit之后,父进程才执行.
当进程调用exec函数时,一个新程序替换了当前进程的正文,数据,堆和栈段。这样,前面的拷贝工作就是白费力气了,
这种情况下人就想出了vfork。vfork并不复制父进程的进程环境,子进程在父进程的地址空间中运行,如果子进程修改数据则会带来未知的结果。

在创建一个新进程之后可以调用exec函数簇来执行新的进程,这些函数簇如下所示:

int execl(const char *pathname, const char *arg, ...);
int execlp(const char *filename, const char *arg, ...);
int execle(const char *pathname, const char *arg, ..., char *const envp[]);
int execv(const char *pathname, char *const argv[]);
int execvp(const char *filename, char *const argv[]);
int execve(const char *pathname, char *const argv[], char *const envp[]);
其中l,p,e,v的代表意义如下:



2.进程和线程的区别:

一个进程的相关信息由以下及部分组成:

task_struct结构包含的基本信息:
1.进程状态(State):
(1)运行状态:当前正在运行的进程;
(2)阻塞状态:处于该状态的进程正在等待某个事件(Event)或某个资源,它肯定位于系统中的某个等待队列(wait_queue)中
(3)就绪状态:CPU 是这些进程唯一等待的系统资源
(4)僵死(终止)状态:进程虽然已经终止,但由于某种原因,父进程还没有执行wait()系统调用,终止进程的信息也还没有回收。顾名思义,处于该状态的进程就是死进程,
这种进程实际上是系统中的垃圾,必须进行相应处理以释放其占用的资源。
2.进程调度信息
3.标识符(Identifiers):每个进程有进程标识符、用户标识符、组标识符
4.进程通信有关信息(IPC,Inter_Process Communication)
5.进程链接信息(Links):程序创建的进程具有父/子关系。因为一个进程能创建几个子进程,而子进程之间有兄弟关系,在task_struct 结构中有几个域来表示这种关系。
6.时间和定时器信息(Times and Timers):一个进程从创建到终止叫做该进程的生存期(lifetime)
7.文件系统信息(File System):进程可以打开或关闭文件,文件属于系统资源,Linux 内核要对进程使用文件的情况进行记录。
8.虚拟内存信息(Virtual Memory):除了内核线程(Kernel Thread),每个进程都拥有自己的地址空间(也叫虚拟空间),用mm_struct 来描述。
9.页面管理信息:当物理内存不足时,Linux 内存管理子系统需要把内存中的部分页面交换到外存,其交换是以页为单位的。

进程和线程的区别是一个很经典的问题,本文就以下方面进行对比:

(1).进程有自己独立的地址空间;而线程共享进程的地址空间;
linux的进程地址空间为0-4G,其中0-0xbfffffff是用户空间,0xcfffffff-0xffffffff是内核空间,当创建一个线程的时候就相当于从某一个路径开始执行,这个路径的开始就是某个函数的第一条指令的地址,当我们没有创建线程时,假设有void *thread_func(void *arg)函数,我们可能会在进程的某一个位置调用它。在Linux操作系统中,每一个进程首先有thread_info结构,这个结构进程的内核栈存放在一起,通过thread_info可以定位到进程的task_struct,task_struct结构比较复杂,其中有一项是进程中所有线程的数据结构的指针。

(2).一个程序至少有一个进程,一个进程至少有一个线程;在linux系统中,进程可以看做是主线程,如果这个进程没有其他线程,那么这个进程就只有一个主线程,在单线程进程中,可以通过pthread_self()函数和getpid()函数获得。

(3).线程是处理器调度的基本单位,但进程不是;进程是操作系统分配资源的基本单位。创建或撤销进程时,系统要为进程创建和回收进程控制块,分配和回收资源,为此操作系统所付出的开销大于线程的创建和回收。在进程切换中,需要保存当前进程的CPU环境,设置新调度运行进程的CPU环境,线程切换只需要保存少量寄存器的内容,不涉及内存方面的操作。因此从切换角度而言,进程的开销大于线程。

(4).二者均可并发执行,线程的划分尺度小于进程,使得多线程程序的并发性高。由于进程的地址空间是独立的,所以在并发执行上多进程的安全性要高于多线程,但是从代价上看,多线程的创建和销毁代价比多线程小很多,多线程共享数据,但是线程控制和线程同步复杂。以下是一个简单的比较.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值