[操作系统]fy姥爷的考试(第一周)

开宗明义

面对fy姥爷的考试 做一些准备 以防备措手不及

概念了解

文件描述符

对于内核而言,所有打开文件都由文件描述符引用。文字描述符是一个小的非负整数,内核用以标识一个特定进程正在存访的文件。当内核打开一个现存文件或创建一个新文件时,他就返回一个文件描述符。当读,写一个文件时,用open或create返回的文件描述符标示该文件,将其作为参数传送给read或者write。

标准输入,标准输出,标准出错

按惯例,每当运行一个新程序时,所有的shell都为其打开三个文件描述符:标准输入,标准输出,标准出错。如果像简单命令ls那样没有做什么特殊处理,则这三个描述符都连向终端。大多数shell都提供一种方法,使任何一个或所有这三个描述符都能重新定向到某一个文件,例如:

    ls > file.list  

执行ls命令,其标准输出重新定向到名为file.list的文件上。

不用缓存的I/O
函数open,read,write,lseek以及close提供了不用缓存的I/O。这些函数都用文件描述符进行工作;

实例:

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>

int main()
{
    int fd;
    char buf[1000];
    if((fd=open("my_data.dat",O_RDONLY))<0){
    //O_RDONLY只读配置
        printf("Open file fail\n");
        return 0;
    }
    read(fd,buf,sizeof(buf));
    printf("%s\n",buf);
    close(fd);
    return 0;
}
//输出:
Hello World!I am here!
(空行)

read函数返回读得的字节数,此值用作要写的字节数。当到达文件的尾端时,read返回0,程序停止,如果发生了一个读错误,read返回-1。出错时大多数系统函数返回-1。

标准I/O

标准I/O函数提供一种对不用缓存的I/O函数的带缓存的界面。使用标准I/O可无需担心如何选取最佳的缓存长度,例如上一程序的sizeof(buf)参数。另一个使用标准I/O函数的有点与处理输入行有关。

open函数

调用open函数可以打开或创建一个文件

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int open(const char *pathname,int oflag,.../*,mode_t */);
//返回:若成功为文件描述符 若出错为-1

我们将第三个参数写入…,这是ANSI C说明余下参数的数目和类型可以变化的方法。对于open函数而言,仅当创建新文件时才使用第三个参数.

由open返回的文件描述符一定是最小的未用描述符数字。这一点被很多应用程序用来在标准输入,标准输出或标准出错输出上打开一个新的文件。例如,一个应用程序可以先关闭标准标准输出(通常是文件描述符1),然后打开另一个文件,事先就能了解到该文件一定会在文件描述符1上打开。

close函数

可用close函数关闭一个打开文件:

#include<unistd.h>
int close(int filedes);

关闭一个文件时也释放该进程加在该文件上的所有记录锁。
(记录锁的功能是:当一个进程正在读或者修改文件的某一个部分时,它可以阻止其他进程修改同一文件区)
当一个进程终止时,他所有的打开文件都由内核自动关闭。很多程序都使用这一功能而不显式地用close关闭打开的文件。

lseek函数

每个打开文件都有一个与其相关联的”当前文件位移量”。他是一个非负整数,用以度量从文件开始处计算的字节数。通常,读,写操作都从当前文件位移量处开始,并使位移量增加所读或写的字节数。按系统默认,当打开一个文件时,除非指定O_APPEND选择项,否则该位移量被设置为0。

可以调用lseek显式地地位一个打开文件

#include<sys/types.h>
#include<unistd.h>
off_t lseek(int filedes,off_t offset,int whence);

对参数offset参数的解释与惨数whence的值有关
1. 若whence是SEEK_SET 则将该文件的位移量设置为据文件开始处offset个字节。
2. 若whence是SEEK_CUR 则将该文件的位移量设置为其当前值加offset(offset可正可负)
3. 若whence是SEEK_END 则将该文件的位移量设置为文件长度加offset

若lseek成功执行 则返回新的文件偏移量 为此可以用下列方式确定一个打开文件的当前位移量:

    off_t currpos;
    currpos = lseek(fd,0,SEEK_CUR); 

这种方法也可用来确定所设计的文件是否可以设置位移量。如果文件描述符引用的是一个管道或FIFO 则lseek返回-1 并将error设置为EPIPE。

lseek仅将当前的文件位移量记录在内核内,他并不引起任何I/O操作。然后,该位移量用于下一个读或写操作。

未变化吧位移量可以大于文件的当前长度,在这种情况下,对该文件的下一次将延长该文件,并在文件中构成一个空调,这一点是允许的。位于文件中但没有写过的字节都被读为0。

read函数

用read函数从打开文件中读数据。

#includ<unistd.h>
ssize_t read(int filedes,void buff,size_t nbytes);
//返回:读到的字节数 若已到文件尾0 若出错为-1

如read成功 则返回读到的字节数 如已到达文件的尾端 则返回0。
有多种情况可使实际读到的字节数少于要求读字节数。
读操作从文件的当前位移量处开始,在成功返回之前,该位移量增加实际读得的字节数。

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
int main(){
    int fd;
    char buf[1000];
    if((fd=open("my_data.dat",O_RDONLY))<0){
        printf("Open file fail!\n");
        return 0;
    }

    printf("1.Current offset %ld\n",lseek(fd,0,SEEK_CUR));
    //0
    off_t length = lseek(fd,0,SEEK_END);
    printf("2.Current offset %ld\n",lseek(fd,0,SEEK_CUR));
    //23
    lseek(fd,0,SEEK_SET);
    printf("3.Current offset %ld\n",lseek(fd,0,SEEK_CUR));
    //0
    read(fd,buf,length);
    printf("4.Current offset %ld\n",lseek(fd,0,SEEK_CUR));
    //23
    buf[length]='\0';
    printf("%s\n",buf);
    close(fd);
    return 0;
}
I/O效率

如果我们使用read和write函数来复制一个文件,我们应该注意以下几点:
1. 他从标准输入读,写至标准输出,这就假定在执行程序,这些标准输入,输出已由shell安排好。确实,所有常用的shell都提供一种方法,他在标准输入上打开一个文件用于读,在标准输出上创建或重写一个文件。
2. 很多应用程序假定标准输入是文件描述符0,标准输出是文件描述符1。
3. 考虑到进程终止时,unix会关闭所有打开的文件描述符,所以此程序并不关闭输入和输出文件。
4. 程序对文本文件和二进制代码文件都能工作,因为对unix而言,这两种文件并无区别。

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
int main(){
    int fd;
    char buf[1000];
    if((fd=open("my_data.dat",O_RDONLY))<0){
        printf("Open file fail!\n");
        return 0;
    }

    printf("1.Current offset %ld\n",lseek(fd,0,SEEK_CUR));
    //0
    off_t length = lseek(fd,0,SEEK_END);
    printf("2.Current offset %ld\n",lseek(fd,0,SEEK_CUR));
    //23
    lseek(fd,0,SEEK_SET);
    printf("3.Current offset %ld\n",lseek(fd,0,SEEK_CUR));
    //0
    read(fd,buf,length);
    printf("4.Current offset %ld\n",lseek(fd,0,SEEK_CUR));
    //23
    buf[length]='\0';
    printf("%s\n",buf);
    close(fd);

    if((fd=open("new_file.dat",O_WRONLY|O_CREAT))<0){
        printf("Open for write fail\n");
        return 0;
    }   

    write(fd,buf,length);
    close(fd);
    execl("/bin/cat","cat","new_file.dat",NULL);

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值