- day2
- 二、文件IO
- 1.概念
- 在系统中(posix)定义的一组用于输入输出的接口
- posix:可移植操作系统的接口
- 2.特点
- (1).没有缓冲机制,每次调用都会引起系统调用
- (2).围绕文件描述符进行操作,文件描述符都是非负整数(>=0),依次分配
- (3).文件IO默认打开了三个文件描述符,分别是0(标准输入),1(标准输出),2(标准错误)
- (4).可以操作任意类型的文件,目录文件除外。
- 3.函数接口
- 3.1打开文件 open
- int open(const char *pathname, int flags);
- 功能:打开文件
- 参数:
- pathname:文件路径名
- flags:打开文件的方式
- O_RDONLY:只读
- O_WRONLY:只写
- O_RDWR:可读可写
- O_CREAT:创建
- O_TRUNC:清空
- O_APPEND:追加
- O_EXCL:判错
- 返回值:成功:文件描述符;失败:-1
- 当第二个参数中有O_CREAT选项时,需要给open函数传递第三个参数,指定创建文件的权限。
- int open(const char *pathname, int flags, mode_t mode);
- 创建出来的文件权限为指定权限值&(~umask) //umask为文件权限掩码
- 3.2关闭文件 close
- int close(int fd);
- 功能:关闭文件
- 参数:fd:文件描述符
- 3.3读写操作 read write
- ssize_t read(int fd, void *buf, size_t count);
- 功能:从一个已打开的可读文件中读取数据
- 参数:
- fd 文件描述符
- buf 存放位置
- count 期望的个数
- 返回值:
- 成功:实际读到的个数
- 返回-1:表示出错,并设置errno号
- 返回0:表示读到文件结尾
- ssize_t write(int fd, const void *buf, size_t count);
- 功能:向指定文件描述符中,写入 count个字节的数据。
- 参数:
- fd 文件描述符
- buf 要写的内容
- count 期望值
- 返回值:成功:实际写入数据的个数。失败 : -1
- 3.4定位操作 lseek
- off_t lseek(int fd, off_t offset, int whence);
- 功能:设定文件的偏移位置
- 参数:
- fd:文件描述符
- offset偏移量 正数:向文件结尾位置移动 负数:向文件开始位置
- whence 相对位置 SEEK_SET 开始位置 SEEK_CUR 当前位置 SEEK_END 结尾位置
- 返回值:成功:文件的当前位置 。失败:-1
-

- 三、文件IO与标准IO对比
- 四、库
- 1.库的定义
- 通俗讲将用户写好的程序打包形成一个整体;当其他用户或其他模块使用时,只要有这个库文件就可以,不需要源代码。也可以理解为一组预先编译好的方法集合。 本质上来说库就是一种可执行代码的二进制形式。
- 当要使用别人的函数的时候除了包含头文件还要有库 。
- linux系统存储库的位置一般在/lib或/usr/lib
- 2.库的分类
- 静态库和动态库,本质区别是代码被载入时刻不同。
- (1).静态库在程序编译时会被连接到目标代码中。
- 优点:程序运行时将不再需要该静态库;运行时无需加载库,运行速度更快
- 缺点:静态库中的代码复制到了程序中,因此体积较大; 静态库升级后,程序需要重新编译链接
- (2).动态库是在程序运行时才被载入代码中。
- 优点:程序在执行时加载动态库,代码体积小; 程序升级更简单; 不同应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。
- 缺点:运行时还需要动态库的存在,移植性较差
- 3.静态库的制作
- (1).将源文件生成目标文件(.o) gcc -c xxx.c -o xxx.o
- (2).创建静态库文件,用ar指令,它会将许多.o文件转换为.a文件 ar crs libxxx.a xxx.o 静态库文件名命名规范:lib为前缀,紧跟的是静态库名 ,.a为扩展名
- (3).测试静态库使用 gcc xxx.c -L指定库的路径 -l指定库名
- 4.动态库制作
- (1).用gcc创建共享库/动态库 gcc -fPIC -c xxx.c -o xxx.o -fPIC:创建与地址无关的编译程序 gcc -shared -o libxxx.so xxx.o
- (2).测试动态库的使用 gcc xxx.c -L指定库的路径 -l指定库名
-

- 解决方法
- (1).将库拷贝到系统库路径下(/lib /usr/lib)(编译时不需要指定库的路径)
- (2).更改环境变量,将库所在的路径添加到环境变量内 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. (只更改当前终端的环境变量,切换终端环境变量就不存在了)
- (3).添加/etc/ld.so.conf.d/*.conf文件。把库所在的路径加到文件末尾,并执行ldconfig刷新。
- sudo vi /etc/ld.so.conf.d/*.conf 添加动态库存在的路径
- 刷新:sudo ldconfig
- 五、进程
- 1.进程、程序
- 程序:编译好的可执行文件 存放在磁盘上的指令和数据的有序集合 程序是静态的,没有任何执行的概念
- 进程:一次程序的运行过程,一个独立的可调度的任务 执行一个程序所分配资源的总称 进程是动态的,包括创建、调度、执行和消亡。
- 2.进程的特点
- (1).系统会为每个进程分配0-4G的虚拟空间,其中0-3G为每个进程所独有,3-4G为所有进程所共有。
- (2).CPU调度进程时会为进程分配时间片(几毫秒-十几毫秒之间),当时间片用完之后,CPU会再进行其他进程的调度,实现进程的轮转,进而实现多任务操作。
- 3.进程段
- Linux中的进程包含五个段:
- “BSS段”存放程序中未初始化的全局变量的一块内存区域
- “数据段”已初始化的全局变量的一块内存区域。
- “代码段”存放程序执行代码的一块内存区域
- “堆段”存放进程运行中被动态分配的内存段
- “栈段”又称为“堆栈段”存放的是函数的返回地址、函数的参数以及程序中的局部变量
- 4.进程分类
- 交互进程:该类进程是由shell控制和运行的。交互进程既可以在前台运行,也可以在后台运行。该类进程经常与用户进行交互,需要等待用户的输入,当接收到用户的输入后,该类进程会立刻响应,典型的交互式进程有:shell命令进程、文本编辑器等。
- 批处理进程:该类进程不属于某个终端,它被提交到一个队列中以便顺序执行。
- 守护进程:该类进程在后台运行。它一般在Linux启动时开始执行,系统关闭时才结束。
- 5.进程状态
- (1).运行态(TASK_RUNNING):R 指正在被CPU运行或者就绪的状态。这样的进程被成为runnning进程。
- (2).睡眠态(等待态): 可中断睡眠态(TASK_INTERRUPTIBLE)S:处于等待状态中的进程,一旦被该进程等待的资源被释放,那么该进程就会进入运行状态。 不可中断睡眠态(TASK_UNINTERRUPTIBLE)D:该状态的进程只能用wake_up()函数唤醒。
- (3).暂停态(TASK_STOPPED):T 当进程收到信号SIGSTOP、SIGTSTP、SIGTTIN或SIGTTOU时就会进入暂停状态。可向其发送SIGCONT信号让进程转换到可运行状态。
- (4).死亡态:进程结束 X
- (5).僵尸态(TASK_ZOMBIE):Z 当进程已经终止运行,但还占用系统资源,要避免僵尸态的产生
- 6.进程状态切换
- 进程创建后,进程会进入就绪态,当CPU调度到此进程进入执行态,当时间片用完,此进程会进入就绪态等待CPU的下一次调度;当此进程在执行过程中需要执行某些IO操作(阻塞操作)会进入阻塞态,当完成IO操作时又可进入就绪态,等待CPU调度,当进程运行结束进入结束态。
- 7.函数接口
- 7.1创建子进程
- pid_t fork(void);
- 功能:创建子进程
- 返回值: 成功:在父进程中:返回子进程的进程号 >0 在子进程中:返回值为0 失败:-1并设置errno
- 特点
- 1.子进程几乎拷贝了父进程的所有内容,包括代码、数据,缓冲区,系统数据段中的值,栈中的数据,父进程打开的文件,但是PID,PPID不同
- 2.fork之前的代码会被复制但是不会被重新执行,fork之后的代码会被复制,并且父子进程分别执行一遍。
- 3.父子进程的空间相互独立,互不影响,当在相应的进程中改变全局变量,静态变量,都互不影响
- 4.fork之前打开的文件,fork之后拿到的是同一个文件描述符,操作的是同一个文件指针
- 5.若父进程先结束,子进程成为孤儿进程,被init进程所收养,会变成后台进程。
- 6.若子进程先结束,父进程不结束,父进程没有及时回收,子进程就会变成僵尸进程(避免僵尸进程的产生)