1 c的面向对象编程基础
(1)面向过程思想------------- 单片机
把问题分解成一系列的步骤,在函数里面一步步实现步骤,根据需求调用函数。
(2)面向对象的变成思想
把构成问题的事务分解成各个对象,调用对象里面的方法属性解决问题。
(3)面向对象的三大特性
封装:使用结构体进行封装属性
struct parent_class
{
int data; //这是对象的属性
void (*p)(strcut parent_class *pt); //这是一个函数指针,是一类函数的接口---------------多态
};
继承:复用现有的代码(就是儿子继承父亲的属性)
struct child_class
{
int data;
struct parent_class *ptr;
};
多态:就是使用函数指针,实现同一个接口,实现不同函数的调用
2 一切皆文件
(1)Linux内核
屏蔽硬件区别,把所有的硬件设备抽象成文件,提供统一的接口给用户使用。
(2)虚拟文件系统(VFS)
抽象层,对文件的访问实现了 对抽象层的访问。抽象对象:封装了底层读写细节,使用c语言的多态来实现具体文件系统系统的接口。
(3) 特殊文件系统:
进程文件系统:procfs,挂载在/proc,存放进程相关信息,相当于任务管理器。
设备文件系统:devfs,挂载在/dev。存放硬件操作接口。
2文件描述符(是一个文件描述符结构体)
(1)系统io编程:使用linux提供的系统调用来编程
(1)系统调用IO函数
open
write
read
lseek
close
伪代码实现文件的操作
int fd;
fd = open(filename,flags,mode); //file:是文件的路径,可以绝对路径与相对路径:flag:打开文件的模式(只读、只写、可读可写):mode:就是文件的权限设置
lseek(fd,offset,whence); //fd:文件描述符,可以通过这个文件描述符找到文件的所在位置:offset:指定文件的偏移量
write(fd,buf,write_len);
read(fd,buf,read_len)
close(fd);
(2)文件描述符
就是特殊的索引,实际就是进程file_struct结构体成员fd_array的数组下标(0,1,2这三个文件描述符已经被系统所占用,代表标准输入,标准输出与标准出错三个文件)
(3)文件打开模式
主模式:(他们是相互互斥的,只能同时使用一个)
- O_RDONLY:只读模式
- O_WRONLY:只写模式
- O_RDWR:读写,模式
副模式:
- O_CREAT:当文件不存在,需要去创建文件
- O_APPEND:追加模式
- O_DIRECT:直接IO模式
- O_SYNC:同步模式
- O_NOBLOCK:非阻塞模式
(3)
(4)open_close函数详解
头文件
open需要的
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
write需要的
#include <unistd.h>
函数原型:
当文件存在时
int open(const char* pathname,int flags)
当文件不存在时
int open (const char* pathname,int flags | int perms)
/下面是使用教程
open_close
vim open_close.c
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unisted.h>
#include<stdio.h>
int main()
{
int fd;
fd = open("./test.txt",O_RDONLY|O_CREAT,0666);//这个是 打开文件./test.txt文件,不存在就创建
if(fd <0 )
{
printf("error! error code %d:\n",fd)
}
return 0;
}
(5)read-write函数详解
头文件
#include <unistd.h>
函数原型
- read函数
-
- ssize_t read(int fd,void *buff,size_t count)
- 返回值
- 成功:
- count:成功读取全部字节
- 0~count:
- 剩余文件长度小于count
- 读取期间被异步信号打断
- 失败:
- -1,读取错误
write函数
- write函数与read相同
- ssize_t write(int fd,void *buff,size_t count)
- 返回值
- 成功:
- count:成功写入全部字节
- 0~count:
- 写入期间被异步信号打断
- 失败:
- -1,读取错误
下面是使用教程:实现一个文件复制
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unisted.h>
#include<stdio.h>
int main( int argc ,char (*argv)( ) )
{
int fd1,fd2;
char buf[1024];
int read_size=0;
fd1 = open(argv[1],O_RDONLY);
fd2 = open(argv[2],O_RDONLY|O_CREAT,0666)//最后一个参数0666,设置成了文件可读可写
if(fd1 <0 || fd2 <0 )
{
printf("open error,error code fd1:%d fd2:%d\n",fd1,fd2);
return -1;
}
while(1)
{
read_size = read(fd1,buf,sizeof(buf));
if(read_size == 0)
{
break;
}
write(fd2,buf,sizeof(buf));
}
close(fd1);
close(fd2);
return 0;
}
(6)lseek-sync函数详解
lseek
头文件:#include <unistd.h>
函数原型:off_t lseek(int fd,off_t offset,int whence)
返回值:
- 若whence为SEEK_SET,基准点为文件开头
- 若whence为SEEK_CUR,基准点为当前位置
- 若whence为SEEK_END,基准点为文件末尾
- 失败
- -1读取错误
/下面是对lseek函数的测试程序
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unisted.h>
#include<stdio.h>
int main(int argc ,char **argv)
{
int fd =0;
fd = open("test.txt",O_RDONLY|O_CREAT,0666);//最后一个参数设置成了0666,权限可读可写
if(fd <0 )
{
printf("open error %d:\n",fd);
return -1;
}
write(fd,"hello",sizeof("hello"));
lseek(fd,100,SEEK_CUR) //以当前为基准,往后偏移100个字节
write(fd,"lailin",sizeof("hello"));
sync(); //立即把缓冲区的数据写入磁盘中
close(fd);
}
sync函数
在正常情况下,用户写的buf与磁盘之间还有一个缓冲区,与磁盘打交道过程中,会通过缓冲区
sync函数功能:实现页缓存与回写,就是强制把页缓存的数据写入到磁盘
函数原型:
void sync(void);
(2)C标准库调用io编程:使用Linux提供的c库函数与系统调用来编程
- 与系统调用的区别:系统调用的是使用操作系统内核来完成文件的操作,需要Linux内核工作,如果频繁调用系统调用,无疑增加了内核的工作量。而使用标准的IO编程,是在用户态的状态下开辟一个io缓冲区,仅在需要把数据写入磁盘的时候才调用系统调用,减少了内核的工作量。
- 常见的标准IO函数
- fopen
- fclose
- fwrite
- fread
- fseek
- fflush :实现强制把IO缓存区的数据写入内核的缓冲区
通过这张图片可以看出c标准库函数与系统调用的区别与联系
- 文件IO的五大模式
- 阻塞模式:就是进程在读写文件失败的情况下就自动阻塞自己(退出CPU的运行权)
- 非阻塞模式:就是进程在读写文件失败的情况下不进行阻塞自己
- IO多路复用
- 异步IO
- 信号驱动IO