I/O进程2

  • 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.若子进程先结束,父进程不结束,父进程没有及时回收,子进程就会变成僵尸进程(避免僵尸进程的产生)