如果代码或文章中,有什么错误或疑惑,欢迎交流沟通哦~
## 进程与线程的区别 1. **各自定义**:
进程是操作系统进行资源分配和调度的一个独立单位,具有一定独立功能的程序关于某个数据集合的依次运行活动。
线程被称为轻量级的进程,是进程中的实体,是被操作系统独立调度和分派的基本单位。
-
内存:
进程每启动一个新的,就需要分配独立的内存空间,而线程是在同一个进程下,共享相同的内存空间,因此线程的启动和关闭以及切换的除存需要的系统开销都要比进程小。
-
通信方式:
进程间需要使用进程间通信(IPC, Inter-Process Communication)的方式来进行通信,例如:**管道,信号,消息队列,共享内存,信号量等。**而同一进程中的线程共享相同的内存空间,所以线程之间可以直接访问同一进程内的全局变量,静态变量等数据,线程间通信比进程间通信要容易得多。
-
影响范围:
由于进程具有独立的内存空间,所以一个进程崩溃后,在保护模式下,不会对其他进程产生影响,但是一个线程崩溃后,会导致整个进程崩溃。
-
改变环境:
每个独立的进程有一个完全独立的运行环境,改变自己的运行环境(如改变文件打开方式、改变信号处理方式等)不会影响其他进程。而线程则不同,一个线程改变其运行环境会影响到同在一个进程中的其它线程。
fork()
用fork( )创建进程必须的几个要点:
- 要有一段程序供该进程运行
- 有进程专用的系统堆栈空间
- 有进程控制块PCB,在linux中具体实现是task_struct
- 有独立的内存空间
如果没有自己独立的内存空间,就称为线程。
线程与进程的区别,在于线程没有独立的内存空间。
使用fork()来创建进程
//testFork.c
#include<stdio.h>
#include<unistd.h>
int main()
{ int count=1;
int child;
if(!(child=fork()))
printf("This is son, his count is: %d. and his pid is: %d\n", ++count, getpid());
else
printf("This is father, his count is: %d, his pid is: %d\n", count, getpid());
}
显示结果:
This is son, his count is: 2. and his pid is: 302
This is father, his count is: 1, his pid is: 301
fork() 调用会创建一个新的进程,这个新的进程是当前进程的复制品,被称为子进程。
fork() 函数在父进程中返回新创建的子进程的进程ID,而在子进程中返回0。
也就是说,如果child = fork()
的值为0,则说明在子进程中,将执行
printf("This is son, his count is: %d. and his pid is: %d\n", ++count, getpid());
语句。
否则说明在父进程中,将执行
printf("This is father, his count is: %d, his pid is: %d\n", count, getpid()); }
语句。
这两行打印语句的区别在于,子进程的count
值会加一,且父子进程的pid
是不同的。
vfork()
- 在Unix和类Unix系统中,vfork()是一种特殊的fork()。
- vfork()创建的子进程可能与父进程共享内存,这意味着子进程可以修改父进程的内存空间,这与fork()是不同的。
- 执行vfork()函数创建的进程,仍然是父进程和子进程的关系,有各自独立的进程ID,但在一些系统(如早期的Unix系统)中,vfork()创建的子进程和父进程共享同一地址空间,父进程在子进程结束执行或者调用exec系列函数之前停止执行。这一点与fork()存在明显的差异。
使用vfork()创建子进程
//testVfork.c
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
int main( )
{ int count=1; int child;
printf("Before create son, the father's count is:%d\n", count);
if(!(child=vfork()))
{ printf("This is son, his pid is: %d and the count is: %d\n", getpid(), ++count);
exit(0); }
else
printf("After son, This is father, his pid is: %d and the count is: %d,
and the child is: %d\n", getpid(), count, child);
}
显示结果:
Before create son, the father's count is:1
This is son, his pid is: 4185 and the count is: 2
After son, This is father, his pid is: 4184 and the count is: 2, and the child is: 4185
注意这里有三个打印语句,其中两个打印语句是在父进程当中,
printf("Before create son, the father's count is:%d\n", count);
和printf("After son, This is father, his pid is: %d and the count is: %d, and the child is: %d\n", getpid(), count, child);
这两个语句。
而子进程中的打印语句 printf("This is son, his pid is: %d and the count is: %d\n", getpid(), ++count);
,将父子进程共享空间里的count++
了,所以父进程后一条打印语句也会打印得到count=2
。
用vfork创造线程和父子进程的同步问题
在使用 vfork()
创建子进程后,父进程将会被挂起。父进程的执行只会在子进程调用 exit()
或者执行 execve()
开始新程序后才会继续。这是 vfork()
与 fork()
的一个主要区别。
//testVfork.c
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
int main()
{ int count=1,i; int child;
printf("Before create son,the father's count is:%d\n",count);
if(!(child=vfork()))
{ for(i=0;i<100;i++)
{ printf("This is son, The i is: %d\n", i);
if(i==70) break; }
printf("This is son, his pid is: %d and the count is: %d\n", getpid(), ++count);
exit(0);
}
else
printf("After son, This is father, his pid is: %d and the count is: %d,and the child is: %d\n",getpid(),count,child);
}
显示结果:
…… ……
This is son, The i is: 68
This is son, The i is: 69
This is son, The i is: 70
This is son, his pid is: 4434 and the count is:2
After son, This is father, his pid is: 4433 and the count is: 2, and the child is: 4434