进程(1)—— 基础理论及fork()
来源:互联网 发布:java获取文件修改时间 编辑:程序博客网 时间:2024/03/29 18:08
一 进程基础理论
进程 - 一个在内存中运行的程序
主流的操作系统基本都支持多进程。
Linux中查看进程的方法
ps - 查看本终端启动的进程
ps -aux Linux专用的查看进程
ps -ef Unix/Linux通用的查看进程
显示的东西有所差别,Unix系统不直接支持ps -aux ,但/usr/ucb/ps -aux 可以执行。
kill -9 进程ID 可以杀进程。
如果进程a启动了进程b,a叫父进程,b叫子进程。
Unix/Linux的进程启动次序,首先内核启动0进程,0进程 启动 1进程和2进程(有些Linux只启动1进程),1进程 和 2进程 再 启动其他所有进程。
进程的常见状态:
S - 休眠状态(省资源)
s - 有子进程
O - 可运行状态
R - 运行状态
Z - 僵尸进程(已经结束但资源没有回收的进程)
父子进程之间的关系:
1. 父进程启动子进程后,父子进程同时运行。
2. 如果子进程先结束,子进程会给父进程发信号,由父进程负责回收子进程的相关资源。
3. 如果父进程先结束,子进程变成孤儿进程,孤儿进程会把init进程(进程1)作为新的父进程,init进程也叫孤儿院。
4. 如果子进程先结束,同时发的信号父进程没有收到或者子进程没有发信号,子进程就变成僵尸进程。
#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main(){ printf("父进程%d开始运行\n",getpid()); pid_t pid = fork(); if(pid == 0){ printf("子进程%d开始运行,父进程%d\n", getpid(),getppid()); sleep(3); printf("休眠结束,父进程%d\n",getppid()); exit(0); } sleep(1); printf("父进程%d结束\n",getpid()); return 0;}
二 进程ID
关于进程的ID - PID
进程ID在同一时刻 确保唯一,但支持延迟重用。
取进程ID的函数:
getpid() - 取当前进程id
getppid() - 取当前进程的父进程的PID
getuid() geteuid() - 取有效用户的ID
三 创建子进程函数 - fork()/vfork()
pid_t fork(void); - 非常简单但非常复杂的函数
fork()是通过复制自身(父进程)创建子进程。
fork()创建的子进程,会复制父进程除代码区之外的内存区域,但和父进程共享代码区。
#include <stdio.h>#include <unistd.h>int main(){ printf("begin\n"); pid_t pid = fork();//创建一个子进程 printf("end:%d\n",pid);}
fork()之前的代码 父进程执行一次,fork()之后的代码父子进程分别执行一次。fork()函数会有两次返回,父进程返回 子进程ID,子进程返回0。因此可以用fork()返回值区分父子进程。返回 -1 代表失败。
if(pid == 0){
//子进程
}else{
//父进程
}
#include <stdio.h>#include <unistd.h>#include <stdlib.h>int main(){ pid_t pid = fork(); if(pid == -1) perror("fork"),exit(-1); if(pid == 0){//子进程 printf("我是子进程%d,父进程是%d\n", getpid(),getppid()); //exit(0);//子进程可以使用exit()退出 }else{ printf("我是父进程%d,子进程是%d\n", getpid(),pid); } printf("end\n"); return 0;}
fork()之后,父子进程同时运行,但谁先运行,谁先结束都不确定。不同的操作系统对于谁先运行算法不同。
#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>int i1 = 100;//全局int main(){ int i2 = 100;//栈,子进程的i2是复制得到 char* str = malloc(20);//堆 strcpy(str,"abcd"); pid_t pid = fork(); int i3 = 100;//栈,父子进程分别定义 if(pid == 0){//子进程 i1 = 200; i2 = 200; i3 = 200;int i4 = 200; strcpy(str,"1234"); printf("child:i1=%d,i2=%d,i3=%d,i4=%d,str=%s,& i1=%p\n",i1,i2,i3,i4,str,&i1); exit(0); } sleep(1); printf("father:i1=%d,i2=%d,i3=%d,str=%s,&i1=%p\n",i1,i2,i3,str,&i1); return 0;}
fork()如果复制文件描述符时,只复制描述符,不复制文件表。
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>int main(){ int fd = open("a.txt",O_RDWR|O_CREAT,0666); if(fd==-1) perror("open"),exit(-1); pid_t pid = fork(); if(pid==0){//子进程 printf("child:fd=%d\n",fd); write(fd,"hello",5);//复制描述符 close(fd); //不复制文件表 exit(0); } printf("father:fd=%d\n",fd); write(fd,"12345",5); close(fd);}
fork()创建子进程之后,父子进程代码可以同时执行(并行)。
练习:模拟聊天室
启动10个子进程,每个子进程休眠1秒,然后打印进程xxx退出了聊天室。 xxx就是子进程的id。然后子进程就结束了。
效果是 10个子进程同时结束。
注意:子进程一定要写exit()
ps -aux 查看一下是否有没有杀掉的子进程
kill -9 进程ID 杀进程
#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main(){ printf("聊天室开始运行\n"); int i; for(i=0;i<10;i++){ pid_t pid = fork(); if(pid == 0){ sleep(1); printf("进程%d离开了\n",getpid()); exit(0); } }}
四 进程的结束
进程结束的方式:
正常结束:
main()执行了return
执行了exit()/_exit()/_Exit()
最后一个线程结束
非正常结束:
信号
被其他线程取消了最后一个线程
exit()/_exit()/_Exit()的区别:
1 _exit()和_Exit()本质上是一样的,区别只是前者是uc函数,后者是标C函数。
2 exit() 和 _Exit()区别是 exit()并不是立即退出,在退出前会调用某些函数,只要函数用atexit(函数指针)注册,退出前就会被调用。_Exit()是立即退出,不会做任何额外的事情。
大多数情况下,退出调用exit(int) 即可。
#include <stdio.h>#include <stdlib.h>void fa(){ printf("fa() is call\n");}int main(){ atexit(fa);//exit()之前要调用fa函数 printf("开始退出进程\n"); exit(0); //正常退出,会调用注册过的函数 //_Exit(0); //立即退出,不调用其他函数 printf("进程结束了\n"); return 0;}
- 进程(1)—— 基础理论及fork()
- Oracle数据库 —— 基础理论及SQL之select语句(1)
- Linux进程——fork<1>
- python中进程创建—fork()
- (二十二)进程——进程原语fork
- linux——fork(进程)
- Linux操作系统基础理论(2)----fork系统调用
- 四旋翼姿态解算——基础理论及推导
- 数据建模基础理论 – 数据建模及规范化(1)
- linux内核——从fork()看进程管理
- linux—fork的那些事(僵尸进程)
- linux下进程间通信方式之(1)-管道及fork()函数
- Linux进程——fork函数
- linux 进程学习体会——fork()
- Perl多进程实践——fork
- 小记——fork与进程
- 多进程编程——fork()
- 创建新进程——fork函数
- Matlab中num2str函数的用法
- 8.6 单片机按键消抖
- 8.7 单片机矩阵按键的扫描
- 8.8 简易加法计算器
- 9.1 单片机IO口的结构
- 进程(1)—— 基础理论及fork()
- 9.2 单片机上下拉电阻
- WARN: Establishing SSL connection without server's identity verification is not recommended.
- 9.3 电机的分类
- java 中的clone方法 ,详解
- 9.4 28BYJ-48步进电机
- 体会大师们的智慧-插值查找
- 9.5 让电机转起来
- Two Sum