IO进程
一、 标准IO篇
1. 标准IO的定义:
在C库中定义的一组专门用于输入输出的函数。
2. 标准IO的特点:
通过缓冲机制减少系统调用的次数,提高效率;围绕流进行操作,流用FILE*描述,FILE是保存文件属性信息的结构体;默认打开三个流,即stdin(标准输入)、stdout(标准输出)、stderr(标准错误)。
3. 缓存区的分类:
全缓存(文件相关)、行缓存(终端相关)、不缓存(没有缓存区)。
4. 刷新缓存的条件:
全缓存:程序正常退出;缓存区满刷新;fflush强制刷新。
行缓存:程序正常退出;遇到\n刷新缓存区;缓存区满刷新;fflush强制刷新。
二、 文件IO篇
1. 文件IO的定义:
在posix(可移植操作系统接口)中定义的一组用于输入输出的函数。
2. 文件IO的特点:
没有缓冲机制,每次操作都会引起系统调用;
围绕文件描述符进行操作,文件描述符为非负整数从零开始顺序分配;
默认打开三个文件描 述 符即0(标准输入)、1(标准输出)、2(标准错误);
可以操作除目录以外的任意类型文件。
三、 标准IO与文件IO的对比
四、 目录与库篇
1. 库的定义:
库就是把一些常用函数的目标文件打包在一起,提供相应的函数接口便于使用,本质上是一种可执行代码的二进制形式。
2. 静态库与动态库的本质区别:
代码被载入的时刻不同。
3.静态库与动态库的优缺点:
静态库:
优点:程序运行时将不再需要该静态库;运行时无需加载库,运行速度更快。
缺点:静态库中的代码复制到了程序当中,因此程序体积较大;静态库升级后,程序需要重新编译链接。
动态库:
优点:程序在执行时加载动态库,代码体积较小;程序升级更加简单;不同的程序如果调用相同动态库,内存中只需存在一份该动态库。
缺点:运行时还需要动态库的存在,因此移植性较差。
4. 静态库的制作:
将源文件编译生成目标文件(gcc -c add.c -o add.o);
创建静态库用ar命令,将.o转换成.a(ar crs libmyadd.a add.o);
测试使用静态库(gcc main.c -L. -Imyadd);
执行a.out。
5. 动态库的制作:
用gcc创建共享库(gcc -fPIC -c hello.c -o hello;gcc -shared -o libmyhello.so hello.o);
测试动态库的使用(gcc main.c -L -Imyhello);
使用前把库拷贝到/usr/lib或/lib目录下。
五、 进程篇
1. 进程的定义:
程序:编译好的可执行文件;
存放在磁盘上的指令和数据的有序集合(文件);
程序是静态的,没有任何执行的概念。
进程:进程是一个独立可调度的任务;
执行一个过程所分配的资源的总称;
进程是程序的一次执行过程;
进程是动态的,包含创建、调度、执行和消亡。
2. 进程的特点:
每个进程的地址空间都是相互独立的,系统会为每个进程分配0~4G的虚拟空间,其中0~3G为用户空间,每个进程独立;
3G~4G为内核空间,所有进程共享;
系统会为每个进程分配时间片,当一个进程的时间片用完时,CPU会调度另一个进程,从而实现进程调度的切换。
3. 进程的分类:
交互进程:该类进程由shell控制和运行,交互进程既可以在前台运行,也可以在后台运行。该类进程经常与用户进行交换,需要等待用户的输入,当接收用户输入后,该类进程会立刻响应。(典型的有:shell命令进程、文本编辑器等)
批处理进程:该类进程不属于某个终端,它被提交到一个队列中以便顺序执行。
守护进程:该类进程在后台运行,一般在Linux启动时开始执行,系统关闭时才结束。
4. 进程的状态:
R(运行态)、S(可中断睡眠态)、D(不可中断睡眠态)、T(暂停态)、X(死亡态)、Z(僵尸态)。
5. 子进程(fork)的特点:
子进程几乎拷贝了父进程的全部内容。包括代码、数据、系统数据段中的pc值、栈中的数据、父进程中打开的文件等(但他们的PID\PPID是不同的);
父子进程有独立的地址空间,互不影响;若父进程先结束,子进程称为孤儿进程,被init进程收养,子进程变为后台进程;
若子进程先结束,父进程如果没有及时回应,子进程变为僵尸进程。
6. exit与return的区别:
exit不管在子函数还是主函数中都可以结束进程;
return当子函数中有return时返回到函数调用位置,并不结束进程。
7. 守护进程的特点:
守护进程是后台进程;
生命周期比较长;
从系统启动时开启,系统关闭时结束;
它是脱离终端控制且周期执行的进程。
8. 守护进程的创建过程:
创建子进程,父进程退出(让子进程变为孤儿进程进而成为后台进程);
在子进程中创建新的会话(让子进程成为会话组组长进而完全脱离终端);
改变进程运行路径为根目录(让进程运行路径不能被删除或卸载);
重设文件权限掩码(增大进程创建文件时权限进而提高灵活性);
关闭文件描述符(将不需要的文件关闭)。
六、 线程篇
1. 线程的定义:
线程是一个轻量级的进程,为了提高系统的性能引入线程;
Linux里同样用task_struct来描述一个线程;
线程和进程都参与统一的调度;
在同一个进程中创建的线程共享该进程的地址空间。
2. 线程的特点(线程与进程的区别):
共性:都为操作系统提供了并发执行能力。
不同:
调度和资源:线程是系统调度的最小单位。进程是资源分配的最小单位。
地址空间方面: 同一个进程创建的多个线程共享进程的资源,进程的地址空间相互独立。
通信方面:线程通信较为简单,通过全局变量即可实现(需要考虑临界资源访问问题)。进程通信比较复杂,需要借助进程间的通信机制(3G~4G内核空间)。
安全性方面:线程安全性较差一些,当进程结束时会导致所有线程退出。进程相对安全。
七、 线程同步与互斥
1. 线程同步的定义:
同步指的是多个任务(线程)按照约定的顺序相互配合完成一件事情。
2. 线程同步的机制:
通过信号量实现线程间同步。
3. 信号量的特性:
p操作:
当信号量的值大于0时,可以申请到资源,申请资源后信号量的值减1;
当信号量的值等于0时,申请不到资源,函数阻塞。
v操作:
不阻塞,执行释放操作,信号量的值加1.
4. 线程互斥的定义:
一次仅允许一个进程所使用的资源。
临界区即一个访问共享资源的程序片断。
互斥即为多个线程在访问临界资源时,同一时间只能一个线程访问。
互斥锁即实现互斥机制,主要用来保护临界资源,每个临界资源由一个互斥锁来保护,线程必须先获得互斥锁才能访问临界资源,访问完资源后释放该锁。如果无法获得锁,线程会阻塞直到获得锁为止。
5. 死锁的定义:
指两个或两个以上的进程/线程在执行过程中,由于竞争资源或由于彼此间通信而造成的一种阻塞现象,如果无外力作用,他们都将无法推进下去。
6. 产生死锁的条件:
互斥使用,即当资源被一个线程占有时,别的线程不能使用;
不可抢占,即资源请求者不能从资源占有者手中夺取资源,只能由资源占有者主动释放;
请求和保持,即当资源请求者在请求其他资源的同时保持对原有资源的占有;
循环等待,即存在一个等待队列,形成等待环路。
八、 进程间通信
1. 进程间的通信方式:
早期的进程间通信:
无名管道、有名管道、信号;
system V IPC:
共享内存、消息队列、信号灯集;
BSD:
套接字。
2. 无名管道的特点:
只能用于具有亲缘关系的进程之间的通信;
半双工的通信模式,具有固定的读端和写端;
管道可以看成是一种特殊的文件,对于他的读写可以使用文件IO进行操作;
基于管道是通过文件描述符的通信方式,存在f[0]读端和f[1]写端。
3. 无名管道注意事项:
当管道中无数据时,读操作会阻塞;
管道中无数据将写端关闭,读操作会立即返回(不阻塞);
管道中装满(64K)数据写阻塞,一旦有4K写继续;
只有在管道的读端存在时,向管道中写入数据才有意义否则导致管道破裂。
4. 有名管道的特点:
有名管道可以使互不相关的两个进程相互通信;
有名管道可以通过路径名来指出,在文件系统中可见但内容存放在内存当中;
进程通过文件IO来操作有名管道;
有名管道遵循先进先出的规则;
有名管道不支持lseel()操作。
5. 无名管道与有名管道的对比:
6. 信号的定义:
信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了那些系统事件;
如果该进程当前处于未执行状态,则该信号由内核保存起来,直到该进程恢复执行再传递给她;
如果一个信号被进程设为阻塞,则该信号的传递被延迟,直到阻塞取消才能被传递给进程。
7. 信号的特点:
唯一的异步通信
8. 信号的响应方式:
忽略信号、捕捉信号、执行缺省操作。
9. 信号的种类:
SIGKILL(结束进程,不能被忽略不能被捕捉)
SIGSTOP(结束进程,不能被忽略不能被捕捉)
SIGINT(结束进程,ctrl+c)
SIGTSTP(暂停信号,ctrl+z)
SIGOUT(退出信号,ctrl+\)
10. 消息队列的特点:
消息队列是IPC对象的一种;
消息队列由消息队列ID来唯一标识;
消息队列就是一个消息的列表,用户可以在消息队列中添加消息、读取消息等;
消息队列可以按照类型来发送/接收消息。
11. 消息队列的步骤:
产生key值ftok;
创建或打开消息队列;
添加消息:按照类型把消息添加到已打开的消息队列末尾;
读取消息:可以按照类型把消息从消息队列中取走;
删除消息队列。
12. 共享内存的特点:
共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝;
为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间;
进程就可以直接读写这一内存区而不需要进行数据的拷贝,从而大大提高的效率;
由于多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等。
13. 共享内存的步骤:
创建key值;
创建或打开共享内存;
映射共享内存到用户空间;
撤销映射;
删除共享内存。
14. 信号灯集的特点:
信号灯(semaphore),也叫信号量。它是不同进程间或一个给定进程内部不同线程间同步的机制;
System V的信号灯是一个或者多个信号灯的一个集合。其中的每一个都是单独的计数信号灯。
而Posix信号灯指的是单个计数信号灯。通过信号灯集实现共享内存的同步操作。
15. 信号灯集的步骤:
创建或打开信号灯集:semget;
初始化信号灯:semctl;
PV操作:semop;
删除信号灯集:semctl。