当前位置: 首页 > news >正文

logo灵感网站网站备案期间 搜索引擎

logo灵感网站,网站备案期间 搜索引擎,如何自己做微信小程序,顺义网站做的比较好的公司前言 1)在Linux下面,一切皆文件,文件文件内容文件属性 2)在访问文件是,都得先将文件打开,修改文件的本质其实还是通过执行代码的形式修改。 3)文件是被进程打开的,一个进程可以打…

前言

1)在Linux下面,一切皆文件,文件=文件内容+文件属性

2)在访问文件是,都得先将文件打开,修改文件的本质其实还是通过执行代码的形式修改。

3)文件是被进程打开的,一个进程可以打开多个文件,操作系统会将打开的文件进行管理,被打开的文件被加载到内存中,称为内存文件,未被打开的文件存放在磁盘上,称为磁盘文件。

本文对进程和文件之间的关系,以及操作系统如何对文件进行管理

一、C语言接口与重定向

        在C语言中,提供了打开文件接口fopen,通过查询man手册,其参数有两个,第一个为想要打开的文件名,第二个为打开方式,打开方式有以下12中,其中r表示读,w表示写,a表示追加,b表示二进制,+表示读写,只要带r的打开方式文件不存在就报错,只要带w的打开方式文件不存在就创建。以w形式打开文件,文件会被自动清空,以a方式打开文件,向文件内写入内容,内容追加到文件末尾

打开方式含义文件不存在处理方式
r只读报错
w只写创建新文件
a只写,打开后文件指针指向末尾创建新文件
rb只读,打开二进制文件报错
wb只写,打开二进制文件创建新文件
ab只写,打开二进制文件后指针指向末尾报错
r+读写出错
w+读写创建新文件
a+读写,打开后文件指针指向末尾创建新文件
rb+读写,打开一个二进制文件报错
wb+读写,打开一个二进制文件创建新文件
ab+读写,打开二进制文件后指针指向末尾创建新文件

验证重定向的文件打开方式

[root@hcss-ecs-e53a test5]# cat log.txt 
hello world
[root@hcss-ecs-e53a test5]# echo "hello">log.txt 
[root@hcss-ecs-e53a test5]# cat log.txt 
hello
[root@hcss-ecs-e53a test5]# >log.txt 
[root@hcss-ecs-e53a test5]# cat log.txt 

使用>重定向后,发现原来的内容被覆盖,如果左边为空,重定向结果是文件内容被清空,所以可以推断出,>重定向的打开文件方式是w

[root@hcss-ecs-e53a test5]# echo "hello world" >>log.txt 
[root@hcss-ecs-e53a test5]# cat log.txt 
hello world
[root@hcss-ecs-e53a test5]# echo "hello world" >>log.txt 
[root@hcss-ecs-e53a test5]# echo "hello world" >>log.txt 
[root@hcss-ecs-e53a test5]# echo "hello world" >>log.txt 
[root@hcss-ecs-e53a test5]# echo "hello world" >>log.txt 
[root@hcss-ecs-e53a test5]# cat log.txt 
hello world
hello world
hello world
hello world
hello world

使用>>对文件重定向,发现原来的内容没有被覆盖,新的内容追加到了文件末尾,所以推断出,>>重定向的打开方式是a

二、C语言文件读写接口

fgets(char *s, int size, FILE *stream),整行读取,遇到回车换行或结尾停止.在文本方式时使用。且会在末尾追加一个'\0',占据一个字符,所以实际读取字符数为size-1。

fread(void *ptr, size_t size, size_t nmemb, FILE *stream),读取二进制流,参数为写入的指针,读取单元字符大小,字符数量,目标流。末尾会插入一个

fputs(const char*str,FILE*stream),写入字符串流,参数为字符串和需要写入的文件流。

fwrite(const void*ptr,size_t size,size_t nmemb,FILE* stream),写入二进制流,参数为需要写入的内容,基本单元的大小,需要写入几个基本单元,以及需要写入的文件流。返回值为写入了多少个基本单位

三、Linux下文件I/O接口

1.当前路径

进程在启动的时候,会自动记录当前所在的路径,可以在/proc/PID/cwd查询到当前进程所对应的当前路径

2.程序默认打开的文件流

在开发操作过程中,开发人员

stdin:标准输入-->键盘设备

stdout:标准输出-->显示器设备

stderr:标准错误-->显示器设备

所以,可以对stdout和stderr进行写入后显示屏显示指定内容。例如,使用printf对stdout进行写入,使用fprintf对指定流进行写入等。可以通过读取stdin内容读取键盘输入的数据,例如,使用scanf和fread读取标准输入流数据。

3.文件操作

1.通过C语言操作文件

2.通过系统调用操作文件

1)open

open(const char * filename,int flags),以特定的方式打开文件,返回值为文件打开状态。返回值为文件描述符,返回-1表示文件打开失败。

flags含义
O_RDONLY只读打开
O_WRONLY只写打开
O_RDWR读写打开
O_CREAT若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
O_APPEND追加写
O_TRUNC清空文件内容

在open的flags参数,前三个宏必须存在且仅存在一个,后续选项如有需要直接与前三者进行按位或操作即可。如果文件不存在,则需要在flags参数后面追加mode参数以表示该文件的权限。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(){int fp =  open("log11.txt",O_RDONLY|O_CREAT,0777);if(fp == -1){perror("open error\n");return 1;}return 0;
}

通过观察创建后文件权限位可以看到,指定的文件权限为0777,但是创建后文件的权限为0755,这是因为,在设置文件的权限位的时候,不仅受参数影响,同时会受到umask的影响。如果不想收到umask的影响,可以使用系统接口umask,将该进程下umask设置为0,但是不影响其他地方的umask。

设置前:

设置后:

2)close

close(int fd)关闭打开的文件

3)write

ssize_t write(int fd, const void *buf, size_t count);向指定的文件写入内容,参数fd(目标文件的文件描述符)、buf(需要写入的内容)、count(需要写入的字符数)。如果文件原来有内容,则直接进行覆盖而不是将内容清空。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
int main(){int fd = open("log.txt",O_WRONLY);if(fd == -1){perror("open error\n");return -1;}const char* str = "hahaha\n";write(fd,str,strlen(str));close(fd);int fd1 = open("text.txt",O_WRONLY);if(fd1 == -1){perror("open error\n");return -1;}write(fd1,str,strlen(str));close(fd1);return 0;
}

4)read

ssize_t read(int fd, void *buf, size_t count);读取指定的文件,参数fd(目标文件描述符),buf(内容保存位置),count(表示读取的字符个数)
 

int main(){int fd = open("log.txt",O_RDONLY);if(fd == -1){perror("error\n");return -1;}char buffer[1024];ssize_t s = read(fd,buffer,sizeof(buffer));if(s>0){buffer[s]=0;printf("%s\n",buffer);}close(fd);return 0;
}

四、Linux下的文件I\O

1)fd文件描述符

open的返回值是一个int类型的数字表示文件描述符, -1表示打开失败。打开5个文件,观察他们的fd

int main(){int fd1 = open("log1.txt",O_WRONLY|O_CREAT);int fd2 = open("log2.txt",O_WRONLY|O_CREAT);int fd3 = open("log3.txt",O_WRONLY|O_CREAT);int fd4 = open("log4.txt",O_WRONLY|O_CREAT);int fd5 = open("log5.txt",O_WRONLY|O_CREAT);printf("fd1 is %d\n",fd1);printf("fd2 is %d\n",fd2);printf("fd3 is %d\n",fd3);printf("fd4 is %d\n",fd4);printf("fd5 is %d\n",fd5);
}

发现他们的fd从3开始依次递增。因为0表示标准输入,1表示标准输出,2表示标准错误。

2)Linux进程文件描述

        在Linux系统下面,有一个结构体叫做file 的结构体将打开的文件进行描述管理,结构体中包括了文件的属性、方法集和缓冲区。操作系统将所需要打开的文件从磁盘中读取出来,然后以链表的形式串起来进行管理。

        在进程控制块结构体中,存在一个files_strucet指针,指向一个files_struct结构体对象,这个对象的作用是将进程打开的文件统一管理起来。在file_struct里面,存在一个叫做struct file*fd_array[]的数组(文件描述符表),用于存放文件指针,即将系统打开的文件列表中的指针。而文件对应的下标就是fd(文件描述符),所以可以通过文件描述符对文件进行操作。                                                                              ​​

 

在C语言中,FILE结构体本质就是对struct  file进行封装后的结果。

3)文件fd的文件分配规则

在Linux下面,fd为0,1,2分别为标准输入,标准输出和标准错误,所以,在打开文件时,默认是从3开始依次递增,所以下面代码运行结果为3,4。

int main(){int fd1 = open("log1.txt",O_RDONLY|O_CREAT);int fd2 = open("log2.txt",O_RDONLY|O_CREAT);printf("fd1 is:%d\nfd2 is:%d\n",fd1,fd2);return 0;
}

如果将标准输入关闭,再打开新的文件,结果变成了0,3,分析其原因是stdin打开时,0被占用,当将stdin关闭后,

int main(){close(0);int fd1 = open("log1.txt",O_RDONLY|O_CREAT);int fd2 = open("log2.txt",O_RDONLY|O_CREAT);printf("fd1 is:%d\nfd2 is:%d\n",fd1,fd2);return 0;
}

所以得出结论,fd的分配规则按照文件打开的顺序,从0开始依次分配未使用的数组下标,即为fd。

4)文件重定向

在上面的例子中,可以通过fd关闭标准文件流,再打开文件时,原文件流的fd会被赋给其他文件,该现象就称为文件重定向。

int main(){close(0);close(1);int fd1 = open("log1.txt",O_RDONLY);int fd2 = open("log2.txt",O_WRONLY);char str[1024];scanf("%s",str);printf("%s\n",str);return 0;
}

        在代码中,关闭了标准输入标准输出流,再打开了文件log1.txt和log2.txt,此时这两个文件的fd分别为0和1,再调用scanf和printf函数,发现可以通过这连个函数进行从文件中读和向文件中写。

        重定向的底层原理,在操作系统层,将进程对应的文件描述列表对应下标替换为目标文件,而scanf和printf的底层其实是向下标为0和1的文件读取/写入内容。如果以只写的方式打开文件但是不进行写操作,目标文件会被清空。

5)dup2接口

        在上面已经可以实现输出和输入重定向,但是存在一点问题,需要将原文件关闭再按照顺序打开文件。在linux下面,有一个接口,dup2可以直接将文件的fd进行替换,从而实现文件重定向。

dup2(int oldfd,int newfd),oldfd(需要拷贝的目标文件的fd),newfd(需要被替换的文件fd)。

所以上面的代码就可以进行以下修改

int main(){int fd1 = open("log1.txt",O_RDONLY);int fd2 = open("log2.txt",O_WRONLY);dup2(fd1,0);dup2(fd2,1);char str[1024];scanf("%s",str);printf("%s\n",str);return 0;
}

五、C语言缓冲区

1)什么是缓冲区

        文件缓冲区其实就是内存里面的一块空间,在C语言中,其意义是文件操作只需要将需要读写的文件交给缓冲区,再由缓冲区与系统调用直接进行交互,减少了C语言接口调用时间,同时通过暂存的方式,减少了系统调用的次数,从而提高读写效率。

2)缓冲区在哪里

        在打开文件时,调用fopen接口,会返回一个FILE*指针,FILE是一个结构体,里面包含了fd和缓冲区指针。即每一个打开的文件都有一个·独立的缓冲区。在调用C语言接口对文件进行读取的时候,有一个FILE*的参数,其实质就是将文件里的内容拷贝到缓冲区里面,再内部决定何时进行缓冲区的刷新。

3)缓冲区刷新策略

1、无刷新

无刷新就是读取一个数据就即时将内容交给系统,

2、行刷新

当数据遇到'\n'或者'\r'时就进行刷新

3、全刷新

等数据完全完成读写后再对缓冲区进行刷新

4)缓冲区现象观察

       由于标准输出默认是输出到显示屏,属于行刷新,不便于观察,所以在输出的时候将其重定向到log.txt文件中。

int main(){const char* s1="111111111write\n";const char* s2="222222222fprintf\n";const char* s3="333333333fwrite\n";write(1,s1,strlen(s1));fprintf(stdout,"%s",s2);fwrite(s3,strlen(s3),1,stdout);
}

        到目前正常按照顺序将字符串内容写入到log.txt当中,现在在test.c文件末尾加上fork(),再次运行,观察现象。

int main(){const char* s1="111111111write\n";const char* s2="222222222fprintf\n";const char* s3="333333333fwrite\n";write(1,s1,strlen(s1));fprintf(stdout,"%s",s2);fwrite(s3,strlen(s3),1,stdout);fork();
}

        发现后面两个字符串被写入了两次,而第一个字符串只写入一次,第一个字符串使用的是系统接口调用,而后面两个是使用的C语言函数接口。其原因是使用C语言文件接口后,文件内容其实是被写到了文件的缓冲区当中,而并没有直接写入到log.txt文件当中,当fork后,发生写时拷贝,缓冲区以及里面的内容也被子进程拷贝,在进程结束时。子进程和父进程都需要刷新缓冲区,此时就将缓冲区里面的内容通过系统调用写入到了log.txt文件当中,而write系统调用直接就将文件内容写入到了log.txt当中。

http://www.sczhlp.com/news/145005/

相关文章:

  • 哪里可以接网站开发的活网业制作软件
  • 怎样找家做网站的公司如何进行网站管理
  • 微设计公司网站一键logo设计官网
  • 在线学习网站模板wordpress好看的评论
  • 四川中天建设有限公司网站益阳市赫山区建设局网站
  • SSM
  • Mybatis Plus
  • 郑州做网站最好的公司跨境电商具体是做什么的
  • 博客网站程序网站开发逻辑图
  • 没有货源可以开网店吗北京网站优化指导
  • 和淘宝同时做电商的网站如何实现
  • 关于单位建设网站的申请手机网站建设推广方案ppt
  • 以下哪个不是网站开发工具移动端网站开发公司
  • wordpress素材下载站四川省建设建设监理协会网站
  • 给漫画网站做推广本地做的网站怎么解析到域名
  • 手游网站做cpc还是cpm广告号网站的超链接怎么做
  • 宁波建设局网站郑建华wordpress 评论ip拉黑
  • 宜宾seo网站建设设计公司网站的要点
  • 西安做网站选哪家毕设源码网站
  • 新网站怎么做才能让搜狗收录网站集约建设
  • 导航网站头部代码福建省建设局实名制网站
  • 成都高端网站制作公司wordpress做个SNS
  • 网站备案变更域名中山最好的网站建设公司哪家好
  • 如何在企业版社保网站做增员江苏建设科技网
  • C语言 - *进制转*进制 3
  • ThreadLocal详解
  • C语言 - *进制转*进制 2
  • 整页图片广告网站源码网页设计公司的市场评估
  • 网站建设费用明细 xls做网站的一个黑点符号
  • 合肥知名网站建设公司宣传推广网络推广