linux部分c应用部分基础知识
首先linux中所有的操作都是基于文件操作实现的,这是基准。
1.编写程序过程中的注意事项
1.关于goto关键字的说法,在应用层中goto关键字是不提倡使用的,它会是逻辑混乱不好调试与梳理逻辑结构,但是在驱动中goto是很常见的,关于这个关键字使用的侧重点是他会统一的释放资源。(在linux驱动中会按照一定的顺序申请资源,如果有一步申请失败或者是操作失败,会在函数的尾部统一释放资源)应用层与驱动层的侧重点不同。
2.在Linux中关于涉及到资源的这一部分,每次都要考虑到操作失败与资源申请失败的情况。
3.关于函数的linux部分的函数调用可以查看man手册。
2.文件操作部分
首先要区分系统调用与库调用,要搞清楚的是系统调用是内核提供给应用层的,也就是系统调用一端连接的是内核部分实现的文件操作,另外一段连接的是应用层操作。库函数对文件的操作是基于系统调用之上的,库函数的存在是为了兼容不同的操作系统,给用户一个统一的接口,其次对于linux而言,库函一般是带有缓冲的,减少从用户态到内核态的切换次数。
1.系统调用函数(文件io)
系统调用的函数 open("test.txt", O_RDWR | O_CREAT, 0644); write(fd, "aaaaaa", 6);
open("test2.txt", O_RDWR | O_CREAT, 0644);read(fd, buf, 1024);write(fd2, buf, 6);系统调用对文件的操作都是基于文件描述符进行操作的(fd,fd),其中的文件描述符也是一种资源,有数量限制,使用ulimit-n命令可以查看,自已申请分配的文件描述符一般都是从3开始的,0:标准输入,1:标准输出,2:标准错误。
可以使用strerror、perror,这两个函数来打印出函数的错误信息。
使用O_APPEND打开文件时,使用lseek不能改变写的位置偏移量,并且读的位置偏移量还是开头部分。
当读取文件时,O_APPEND标志并不会影响读位置偏移量,即使使用了 O_APPEND
标志,读文件位置偏移量默认情况下依然是文件头
一个进程内多次 open 打开同一个文件,在内存中并不会存在多份动态文件,一个进程内多次open打开同一个文件,不同文件描述符所对应的读写位置偏移量是相互独立的,
复制得到的文件描述符与原文件描述符都指向同一个文件表,所以它们的文件读写偏移量是一样的,可以在不使用O_APPEND标志的情况下,通过文件描述符复制来实现接续写。
2.标准io(c标准库)
库函数 clearerr()用于清除end-of-file标志和错误标志,当调用feof()或ferror()校验这些标志后,通常需要清除这些标志,避免下次校验时使用到的是上一次设置的值,此时可以手动调用 clearerr()函数清除标志。
2. 关于printf()、fprintf()、dprintf()、sprintf()、snprintf(),的区别:printf()函数用于将格式化数据写入到标准输出;dprintf()和fprintf()函数用于将格式化数据写入到指定的 文件中,两者不同之处在于,fprintf()使用FILE指针指定对应的文件、而dprintf()则使用文件描述符fd指定 对应的文件;sprintf()、snprintf()函数可将格式化的数据存储在用户指定的缓冲区buf中。
关于scanf(),fscanf(), sscanf(),区别:scanf()将用户输入(标准输入)的数据进行格式化转换并进行存储,fscanf()函数从指定文件中读取数据,作为格式转换的输入数据,文件通过FILE 指针指定,sscanf()将从参数str所指向的字符串缓冲区中读取数据,作为格式转换的输入数据.
3.io缓冲部分
1.文件io缓冲部分
read()和 write()系统调用在进行文件读写操作的时候并不会直接访问磁盘设备,而是仅仅在用户空间缓冲区和内核缓冲区(kernel buffer cache)之间复制数据,内核稍后会将数据写入到磁盘设备中,具体是什么时间点写入到磁盘,这个其实是不确定的,由内核根据相应的存储算法自动判断。也可以使用fsync()、fdatasync()、sync()手动刷新到磁盘中,fsync()将参数fd 所指文件的内容数据和元数据写入磁盘,fdatasync()仅将参数fd 所指文件的内容数据写入磁 盘,并不包括文件的元数据;sync()会将所有文件I/O 内核缓冲区中的文件内容数据和元数据全部更新到磁盘设备中.也可以在open文件时加入参数O_DIRECT,其有一些限制,不过这个一般不会用到
2.标准io缓冲部分
虽然标准io是对文件io的进一步封装,但在效率、性能上标准 I/O要优于文件I/O,其原因在于标准I/O实现维护了自己的缓冲区,我们把这个缓冲区称为 stdio 缓冲区。C 语言提供了一些库函数可用于对标准I/O的stdio缓冲区进行相关的一些设置,包括setbuf()、setbuffer() 以及 setvbuf();
int setvbuf(FILE *stream, char *buf, int mode, size_t size);其参数解释:stream:FILE指针,用于指定对应的文件,每一个文件都可以设置它对应的stdio 缓冲区。buf:如果参数buf不为NULL,那么buf指向size大小的内存区域将作为该文件的stdio 缓冲区,如果 buf等 于 NULL,那么stdio库会自动分配一块空间作为该文件的stdio缓冲区(除非参数mode 配置为非缓冲模 式)。mode:参数mode用于指定缓冲区的缓冲类型,可取值如下:
4.两者互相转化
库函数 fileno()可以将标准I/O中使用的FILE指针转换为文件I/O中所使用的文件描述符,而 fdopen() 则进行着相反的操作,int fileno(FILE *stream);
3.文件属相部分
在windows中文件是以.后缀进行区分的,在linux中文件不是以.后缀进行划分的,不过文件终归是要给人看的,所以还是得按照正常的格式进行编写。
在linux中可以通过stat,ls命令查看文件的属性。' - ':普通文件 , ' d ':目录文件 , ' c ':字符设备文件 , ' b ':块设备文件 , ' l ':符号链接文件 , ' s ':套接字文件 , ' p ':管道文件
关于stat命令与file命令的区别:stat命令:stat读取的是文件系统的 inode 信息,包括权限、大小、时间戳、设备号等,它不关心文件内容,file命令:
