1、进程!=程序
程序是静态的,而进程是动态的,进程是程序执行的一种状态。
2、进程和程序的区别
1)进程控制块中包含进程的属性
2)程序在磁盘里面,堆栈都是在内存中,程序运行起来都在内存中
3)进程的运行在内存(RAM)中,手机内存指的是运行内存64G,电脑内存指的是硬盘(ROM)
4)初始化的全局变量在数据段,没有初始化的全局变量放在BSS中
代码段存放可执行文件,机器码
5) static声明的变量不在栈中,和全局变量放在一起
栈:参数,返回值,局部变量
堆:malloc
6)一个进程会被分为不同的区域
7)进程控制块(pcb)
PID、进程用户、进程状态、优先级、文件描述符表
3、进程的类型
1)交互进程:最常用的进程,在前台运行且在shell下可以控制
2)批处理进程:提交到作业队列以便顺序执行
3)守护进程:一直在后台运行,不能用shell命令控制
4、进程的状态
1)ps当前状态下的进程
2)ps -e当前状态下Linux所有的进程
3)ps -elf Linux下进程的详细信息
4)进程状态
5)进程标志
6)ps下的目录含义
PID:进程ID
CMD:进程的名称
NI:进程优先级
PRI:进程优先级
SZ:占用内存
C:占用的CPU利用率
7)ps -elf|grep PID
查看某个进程
1)翻页shift+'<'(前翻页)或'>'(后翻页)
2)top -p PID查看某个进程
3)ctrl+c退出
越nice优先级越低
1)一般nice只能调高
2)只有root才能设置为负值
4)renice改变优先级
6、前台和后台的区别
./test在前台运行:
正常情况下ctrl+C可以结束进程,下次该进程对应的代码还是前台运行
ctrl+Z:此时程序进入停止状态
fg+序号进程又重新挂到前台
在Linux下除了0号进程,其他的进程都是由别人创建的
让我们的进程创建子进程
1)代码
子进程B的代码和A的代码相同
但子进程B只执行程序中fork函数之后的代码
2)打印结果
父进程子进程分别打印
3)如何让父子进程分别执行
1)分别对父子进程加一个sleep
父子进程随机运行
子父进程ID
kill掉父进程
子进程的父进程变成了2107,也就是init进程
子进程变成后台进程
kill掉父进程
此时kill掉父进程,子进程消失
子进程也进行了for循环
解决办法:子进程执行结束break
1)不回收
2)回收
僵尸进程:子进程结束,但是没有被父进程回收
出错:
修正:休眠2秒,等子进程结束
3、通过调用exec函数族执行某个程序
4、调用exec函数族进程当前内容被指定的程序替换
5、相当于父子进程执行不同程序
相当于命令“ls -a -l”
执行效果和execl相同
gcc -g -o 编译生成的名字 文件名
显示可以跟踪的进程
可以继续选择跟踪父子进程
set follow-fork-mode child
调试子进程,同时可以切换父进程
info inferiors查看可以运行的进程
inferior 序号
与控制终端连接的进程就是控制进程。
一个终端界面可以理解成一个会话
此时子进程已经被init收养
称为新的会话组长
自己当家做主人了
关闭文件描述符后,不会在打印到屏幕
守护进程不能在屏幕上打印东西,不能接收键盘的输入
没有写守护进程变成后台的方法
守护进程的实现
常用:静态数据、文件描述符、工作目录
常用:错误号、堆栈
线程不是通过Linux内核实现,而是由线程库来实现。
链接错误线程编译要加上-lpthread
主进程退出,创建的线程也会退出
void定义下的arg是任意类型,直接转换成Int类型
相当于进程中的wait函数
pthread_join在主函数中,接收线程结束的返回值
在主函数中:
不阻塞
在线程函数中:
查看内存命令: top -p 进程号
线程回收前
等待线程回收后
ps -eLf |grep detach
1、如果线程申请了一块内存,但线程因为阻塞被取消,则会造成内存泄露
2、线程清理是在线程异常退出之后,进行清理
3、线程的清理函数本质上是宏定义,必须成对使用
push-pop
4、routine函数
return可以结束线程,但是不能出发清理函数
5、可以cancel自己
两种情况:
1)到取消点取消,取消点之前可以取消
2)立即取消
1、临界资源
1)临界资源是只允许一个资源访问的任务,互斥资源
2)外设、磁盘都是临界资源
3)临界区是访问临界资源的代码
1)两个函数的区别
主函数:
1.txt:两个线程随机打印,乱序
结论:读写锁与互斥锁结果相近
5、读写锁-只读
读写锁比互斥锁好的地方是,读写锁允许多个用户一起读。
延长休眠时间
切换到第3个,设置第六行为断点
设置之后,除了选定的线程,其他不执行
进程-进程/主机-主机
开销最大
相当于共享内存,通过管道传递消息
单工通信-每个进程fd[0]和fd[1]只能用一个
只有读操作之后才能打印buf。
1、父进程创建无名管道
父子进程都可以关闭读写管道,无论这一段是读还是写
子进程之间相互通信:
有名管道通过路径名操作,在文件系统中可见,但内容存放在内存中,非亲缘进程间通信,单工通信,先进先出。
读文件时没有内容直接结束,有内容读内容
写文件打开失败情况:
1、BSS存放没有初始化的全局变量。
2、static声明的变量不在栈中,和全局变量放在一起。
3、栈:参数,返回值,局部变量
堆:malloc
4、ps -elf 查看Linux下进程的详细信息
ps -elf|grep PID查看某个进程
top动态查看Linux下进程的实时信息
top -p PID查看某个进程
/proc查看进程的某个目录
5、子进程和父进程执行的代码相同,但子进程只执行程序中fork函数之后的代码(也就是子进程创建后的代码)。
6、fork函数创建子进程成功后,父进程返回子进程的进程号(进程号大于0),子进程返回0。
7、若父进程先结束,子进程变成孤儿进程,被init进程收养变成孤儿进程;若子进程先结束,父进程没有及时回收,子进程变为僵尸进程。
8、子进程通过exit/_exit/return返回,父进程通过wait(&status)回收子进程,wait有返回值。
9、exec函数使得进程当前内容被指定内容替换,exec函数以后的程序没有被执行自己,子进程调用exec函数族,父进程不受影响。
10、gdb调试命令:gcc -g -o 编译生成的名字 文件名
11、关闭文件描述符1,2,3,守护进程不能在屏幕上打印东西,不能接收键盘的输入。
12、内核(kernel)利用文件描述符(file descriptor)来访问文件。文件描述符是非负整数,打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。文件描述符0, 1, 2 默认为 stdin stdout stderr。
13、pthread_join在主函数中,接收线程结束的返回值。pthread_exit 线程结束函数,在线程内,返回值可以是一句提示语句。
14、如果线程申请了一块内存,但线程因为阻塞被取消,则会造成内存泄露
15、线程的清理函数本质上是宏定义,必须成对使用push-pop。
16、外设、磁盘都是临界资源,临界区是访问临界资源的代码。
17、读写锁与互斥锁结果相近,读写锁比互斥锁好的地方是,读写锁可以允许多个用户一起读。
18、条件变量一定要和互斥锁使用
19、无名管道只能父子或兄弟进程间通信,无名管道是单工通讯,有固定读端和写端,需要创建两个文件描述符,pfd[0]用于读管道,pfd[1]用于写管道。
20、有名管道不能使用读写方式打开文件,管道文件可以创建在根目录下,但是不能创建在共享目录下。
21、调用open函数时,可以指定打开的文件描述符是以阻塞方式还是以非阻塞方式。
阻塞概念:read函数在读设备或者管道,或者socket的时候,默认是阻塞的,也就是说,对方如果没有发送数据过来,则read函数就会一直等待数据过来,从代码的角度来说,就是read函数后面的代码不会被执行。
非阻塞概念:read函数在读设备或者管道,或者socket的时候,对方如果没有发送数据过来,read函数也会立即返回,从代码的角度来说,就是read函数后面的代码会马上被执行。