一、IO
1.1 fseek
头文件: #include 原型:int fseek(FILE *stream, long offset, int whence); 功能:读写指针的偏移 参数: stream:目标文件流指针 offset:如何偏移,偏移多少 如果为负数,代表向前偏移,如果偏移出了文件的开头,会返回报错。 如果该数为正数,代表向后偏移,如果偏移除了文件的末尾,会扩大文件,用'\0'来填,那么此类文件称为空洞文件 注意:如果偏移后没有对其进行任何写入操作,内核认为该偏移无效,不会扩大文件大小 whence:基准位置 ------》根据哪一个位置进行偏移 SEEK_SET:根据文件开头进行偏移 SEEK_CUR:根据用户当前位置进行偏移 SEEK_END:根据文件末尾进行偏移 返回值: 成功返回0 失败返回-1
#include <stdio.h> char ch = 0; int main(int argc, char const *argv[]) { FILE *fp = fopen("./1.txt","r+"); if(NULL == fp) { perror("fopen"); return -1; } //文件中的数据为helloworld //从文件的末尾向后偏移----空洞文件 fseek(fp,2000,SEEK_END); fputc('a',fp); ch = fgetc(fp); printf("ch = %c\n",ch); fseek(fp,1,SEEK_CUR); //从当前位置向后偏移一个字节 ch = fgetc(fp); printf("ch = %c\n",ch); fseek(fp,-1,SEEK_END); ch = fgetc(fp); printf("ch = %c\n",ch); return 0; }
1.2 sprintf
头文件: #include 原型:int sprintf(char *str, const char *format, ...); 功能:向一个固定的地址存放字符串(一般用于字符串的拼接) 参数: str:要存放格式化完成的字符串的地址 format:格式化字符串 ...:可变参数(一般放置变量) 返回值: 成功返回输出的字节个数 失败返回负数
#include <stdio.h> int main(int argc, char const *argv[]) { char name[20] = "zhangsan"; int age = 18; char sex = 'w'; char phone[12] = "12345678900"; char buf[123] = {0}; sprintf(buf,"name:%s--age:%d--sex:%c--phone:%s",name,age,sex,phone); printf("buf = %s\n",buf); return 0; }
1.3 snprintf
头文件: #include 原型:int snprintf(char *str, size_t size, const char *format, ...); 功能:按照固定的大小去格式化字符串输出到字符地址中 参数: str:要存放格式化完成的字符串的地址 size:大小(规定要写入str这片地址中的字节大小) format:格式化字符串 ...:可变参数(一般放置变量) 返回值: 成功返回输出的字节个数 失败返回负数
1.4 fprintf
头文件: #include 原型:int fprintf(FILE *stream, const char *format, ...); 功能:格式化输出字符串到文件中(一般用于书写日志文件) 参数: stream:目标文件流指针 format:格式化字符串{固定的字符串和占位符} ...:可变参数(一般放置变量) 返回值: 成功返回输出的字节个数 失败返回负数
#include <stdio.h> int main(int argc, char const *argv[]) { char name[20] = "zhangsan"; int age = 18; char sex = 'w'; char phone[12] = "12345678900"; FILE *fp = fopen("./1.txt","w"); if(NULL == fp) { perror("fopen"); return -1; } fprintf(fp,"name:%s--age:%d--sex:%c--phone:%s",name,age,sex,phone); return 0; }
二、缓冲区
预定义流 在程序开始之前,创建三个文件描述符,分别为0,1,2对应的标准输入,标准输出,标准错误输出,同时也在其基础上封装了三个预定义流指针 标准输入:stdin --->键盘文件 标准输出:stdout --->终端文件 标准错误输出:stderr --->终端文件
#include <stdio.h> int main(int argc, char const *argv[]) { char buf[123] ={0}; // fgets(buf,123,stdin); //从标准输入流中读取数据 //printf("buf = %s\n",buf); //标准输出 // fprintf(stdout,"helloworld%s","123123"); //标准错误输出 fprintf(stderr,"helloworld%s","123123"); while(1); return 0; }
2.1 缓冲区
缓冲区是什么?标准IO在文件IO的基础上封装的一片存放数据的地址(一般用来存放不着急得数据),等到缓冲区这个地址得数据存满,或者说程序员手动刷新缓冲区,空间中得数据会被调用文件IO操作。
全缓冲:一般对文件得操作,缓冲区大小为4096个字节。(页)
刷新缓冲区得条件:
1.缓冲区满刷新缓冲区
2.程序结束刷新缓冲区
3.程序员手动刷新缓冲区
fflush
头文件:#include 原型:int fflush(FILE *stream); 功能:刷新缓冲区 参数:目标文件流指针 返回值: 成功返回:0 失败返回:EOF
#include <stdio.h> #include <unistd.h> int main(int argc, char const *argv[]) { FILE *fp = fopen("1.txt","w"); if(NULL == fp) { perror("fopen"); return -1; } #if 0 while(1) { fprintf(fp,"helloworld"); usleep(10000); } #endif fprintf(fp,"helloworld"); fflush(fp); while(1); return 0; }
2.2 行缓冲:
只有两个行缓冲,标准输入,标准输出,行缓冲得大小为1024个字节
刷新行缓冲得条件:
1.缓冲区遇到\n则刷新缓冲区
2.缓冲区满则刷新缓冲区
3.当标准输入和标准输出一方要使用缓冲区时,正在使用得一方需要让出缓冲区,给另一方使用
4.fflush刷新缓冲区
5.程序结束
#include <stdio.h> int main(int argc, char const *argv[]) { int i = 0 ; //验证缓冲区大小 for(i = 0; i < 1025;i++) { printf("1"); //每次向准备输出输入一个字节 } //验证\n刷新缓冲区 printf("hello world\n"); char buf[123] = {0}; printf("helloworld1"); scanf("%s",buf); while(1); return 0; }
2.3 无缓冲
一般为标准错误输出,一般用于比较着急得数据,所以不会进入缓冲区,直接调用文件IO
一般使用方式:fprintf(stderr,“hello world”);
后续报错信息:使用这种方式
文件IO和标准IO得区别
文件IO属于系统调用,由操作系统提供,速度快,但是频繁调用文件IO会降低内核得工作效率,并且移植性较差。
标准IO是由标准c库所提供,是在文件IO得基础上封装出来得API接口,移植性高并且在文件IO得基础上封装了一片缓冲区,降低了文件IO得调用次数,提高了内核得效率。
所以说我们得根据情况来使用者这两种IO模型。
三、进程
任务:目标结果
程序:是为了完成任务,编写得一段代码,是一个静态得
3.1 进程的概念
进程是程序为了完成任务执行得一次过程,是一个动态的,进程被称为资源分配的最小单位,因为每一个进程在启动初期,都会申请一个0-4G的虚拟空间。
这个空间分为两个部分,0-3G用户空间,3-4G是内核空间,0-3G是进程之间独有的空间,互不影响。3-4G属于多进程共享的空间(后续于进程间通讯使用),因为进程用户空间相互独立,互不影响,所以安全性较高。还会申请一个PCB进程控制块,是一个结构体,tast_struct里面存储了所有的进程资源
如:PC程序计数器,堆栈,文件描述符,进程的状态,进程号等。
操作系统启动时会自动出创建三个进程:
0:负责引导系统启动,也会创建一个1号进程 --》init进程
1:负责初始化硬件,回收资源
2:负责资源的分配,系统的调度
进程之间存在这个一种竞态。执行速度是不一定的,所以父子进程结束的快慢也是不一定的。
3.2 进程的调度机制:
3.3 进程的状态
3.4 进程的标志
进程号(PID):linux分配的进程的编号,每个进程都不一样,方便管理
进程在结束的时候,会释放进程号的所有权,其它进程等待它释放一段时间后分配,并不会结束后立马区分配。
3.5 进程相关的命令:
1.pstree
以树的形式显示所有的进程
如果加上-p参数会显示进程号
2.ps -ef
主要查看父子进程关系
PID 进程ID PPID 父进程ID
3. ps aux
主要查看进程的状态
进程的状态: 1.R:运行态 2.S: 休眠态 3.I:空闲态 4.T:停止态 5.Z:僵尸态 1. <:优先级高进程 2. N:优先级低 3. l:该进程中包含线程 4. +:前台进程 5. s:会话首进程 4. ps -ajx 主要用于查看家族关系
PGID:进程组ID
SID:会话ID
5. top -htop
动态查看进程信息:主要查看进程CPU占用率
6. jobs
查看用户后台进程列表
ctrl + z :会将前台运行的进程暂停保存到后台
fg:会将后台暂停的进程恢复到前台运行
fg + %序列号:将指定的后台暂停程序恢复到前台运行
bg:会将后台暂停程序在后台运行
bg + %序列号:制动哪一个进程
可执行程序名 + &:将进程运行在后台