程序:用计算机语言对算法的具体实现,它是静态的
进程(process):
正在运行的程序.它是动态的
资源管理的最小单位
虚拟内存空间又分:
内核空间:1G(0xC000 0000 - 0xFFFF FFFF)
用户空间:3G 包括: 堆、栈 、代码段 、数据段 、不可访问空间:0 ~ 0x0804 8000(128M)
当我们的进程结束之后,用户空间会随着进程的结束而释放,但内核空间不会,这1G空间需要创建它的父进程来回收,否则会称为僵尸进程(Bug)
Linux下查看进程
ps -ef:查看所有进程及其PID(进程号),系统时间,命令详细目录,执行者等
ps aux :显示不了状态,
top:动态显示系统中运行的程序(一般每隔5s刷新一次)
pstree:以树形结构显示系统当中的进程
kill:输出特定的信号给指定PID(进程号)的进程‘
进程间状态转换图
1.就绪态
(1)就绪状态:进程已获得除CPU外的所有必要资源,只等待CPU时的状态。一个系统会将多个处于就绪状态的进程排成一个就绪队列。
2.运行态 (R) TASK_RUNNING
(2)执行状态:进程已获CPU,正在执行。单处理机系统中,处于执行状态的进程只一个;多处理机系统中,有多个处于执行状态的进程。
3.等待态 (阻塞态)
(3)阻塞状态:正在执行的进程由于某种原因而暂时无法继续执行,便放弃处理机而处于暂停状态,即进程执行受阻。(这种状态又称等待状态或封锁状态)
(1).可中断的等待态 S (标准输入,sleep()) (TASK_INTERRRUPTIBLE)
(2).不可中断的等待态 D (TASK_UNINTERRUPTIBLE)
4.停止态 (T) TASK_STOPPED
5.死亡态 (X) EXIT_DEAD
6.僵尸态 (Z) EXIT_ZOMIE
进程的优先级
进程的优先级范围:-20到19,数字越大,优先级越低
nice:以某种优先级执行我们的程序
renice :可以修改正在运行程序的优先级
进程相关相关函数
创建进程
好处:可以同时处理多项工作,互不干扰
进程执行
1.父子执行顺序:不确定
2.若父进程先结束,子进程未结束,子进程就会称为孤儿进程
3. 若子进程先结束,父进程未结束,但父进程没有回收子进程的内核资源,子进程会称为僵尸进程
进程主动退出 exit _exit
(1).exit()函数叫C语言库提供,库函数._exit()函数叫系统调用函数,Linux系统提供的
(2).exit()自带清理缓冲区,_exit()不清理缓冲区
- 如何避免僵尸进程的产生(waitpid()回收子进程资源)
wait() 阻塞回收
waitpid(); 非阻塞回收
wait(NULL); 阻塞等待任意一个子进程退出,不接受子进程退出的状态
waitpid(-1,NULL,0) 《====》wait(NULL)
接受子进程退出的状态 (宏使用)
exec()函数族:
(1)fork()子进程是为了执行新的程序
(2)可以直接在子进程if中写入新程序的代码,但是不够灵活,因为只能将子进程程序的源代码贴过来执行(必须知道源码,而且源码太长不好控制)比如要执行 ls -la命令就不行。
(3)使用exec运行新的可执行程序(可以把一个编译好的的可执行程序直接加载运行)
(4)我们有了exec族函数后,我们典型的父子进程就是这样的:子进程需要运行的程序被单独编写、单独编译成一个可执行文件(叫hello),项目是一个多进程项目,主程序叫父进程,fork创建了一个子进程后在进程中exec来执行hello,达到父子进程分别作不同的程序(宏观上)同时运行。
守护进程
1.它是守护进程,也就是通常所说的Daemon进程,是Linux三种进程之一,通常在系统启动时运行,在系统关闭时结束.
2.始终运行在后台,后台服务进程
3.独立于任何终端(和终端无关)。
4.周期性地执行某种任务或等待处理特定事件。
守护进程的创建
1.创建子进程,父进程退出. fork() 为了成为叫后台进程
2.创建新的会话 (脱离原来的会话,成为新的会话组长)
3.修改当前目录
4.修改文件掩码
5.关闭从父进程继承下来的文件描述符
线程(thread)
(1).由于进程的地址空间是私有的,因此在进程间上下文切换时,系统开销比较大
(2).为了提高系统的性能,许多操作系统规范里引入了轻量级进程的概念,也被称为线程
(3).在同一个进程中创建的线程共享该进程的地址空间(除了栈区之外)
线程创建
等待线程结束
(1).pthread_join函数在线程退出时,用来清理线程资源。
(2).phtread_join函数会阻塞调用方,直至pthread_join所指的线程退出。
因为线程默认的状态是结合态的,所以,可以通过pthread_detach函数来设置线程为分离态。
pthread_detach函数的特点
使用pthread_detach函数后,使线程处于分离态;
使用pthread_detach函数后,线程在退出后,会自己清理资源
相较pthread_join,使用pthread_detach函数不会阻塞主线程,但是无法获取线程的返回值。
线程退出
pthread_exit()主动退出
.pthread_cancel()被动退出
总结,创建线程一般需要需要创建子函数
证明全局变量,堆区数据是共享的
子线程给主线程传值
线程出现的问题:
互斥
1.多线程访问临界资源时,没有顺序而言,
若线程A访问临界资源,不允许其他线程访问资源。
2.引入互斥锁:用来保证共享数据操作的完整性。
互斥锁
- 定义互斥锁 (全局)
同步:
多线程访问临界资源,按照某种顺序执行
进程间通信方式
无名管道的特点:
(1).具有亲缘关系(父子关系,兄弟关系)间的进程间通信
(2).管道也可以看成是一个特殊的文件,对于它的读写也可以使用普通的read(),wirte()等函数,
它不属于任何文件系统,存在内核当中.
(3).它是一个半双工的通信模式,具有固定的读端(fd[0])和写端(fd[1])。
有名管道
1.适用于两个不相关的进程间的通信,是一个半双工的通信
2.有名管道可以通过路径名来指出,并且在文件系统中可见,两个进程可以把它当成普通文件进行操作,open,read,write,close
3.有名管道必须遵循先进先出的原则,不支持lseek()函数
信号产生
SystemV IPC(进程间通信方式)
1.消息队列
1.消息队列就是一个消息的列表。用户可以在消息队列中添加消息、读取消息等。
2.消息队列可以按照类型来发送/接收消息,相同的类型满足先进先出,不同的类型可以
共享内存
1.共享内存的特点
- 共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝
- 为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间
优点:
进程就可以直接读写这一内存区而不需要进行数据的拷贝,从而大大提高的效率。
缺点:
由于多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等
创建、打开共享内存
映射共享内存,
撤销共享内存