【Linux】系统调用文件操作

系统调用与库函数

文件操作的系统调用,系统调用的实现在内核中,需要用户态切换到内核态使用。

文件操作用库函数和系统调用很相似,但是库函数一般不会切到内核。

库函数的实现在库中,是用户自己的代码。

四个系统调用:

打开:open();

int open(const char* pathname, int flags);//用于打开一个已存在的文件
int open(const char* pathname, int flags,mode_t mode);//用于新建一个文件,
并设置访问权限

参数介绍:

pathname:将要打开的文件路径和名称

flags : 打开标志,如 O_WRONLY 只写打开

O_RDONLY 只读打开

O_RDWR 读写方式打开

O_CREAT 文件不存在则创建

O_APPEND 文件末尾追加

O_TRUNC 清空文件,重新写入

mode: 权限 如: “0600”

返回值: 为文件描述符


读:read();

ssize_t read(int fd, void* buf, size_t count);

参数介绍:

fd 对应打开的文件描述符

buf 存放数据的空间

count 计划一次从文件中读多少字节数据

返回值: 为实际读到的字节数


写:write();

ssize_t write(int fd, const void* buf,size_t count);

参数介绍:

fd 对应打开的文件描述符

buf 存放待写入的数据

count 计划一次向文件中写多少数据


关闭:close();

int close(int fd);

参数介绍:

fd 要关闭的文件描述符


文件描述符

Linux系统没有文本和二进制之分,所有的东西都是文件,文件描述符是一个整形数字,储存在PCB的文件描述符表中(一个数组),它从0开始递增,是文件的一个id。

每打开一个文件,就会在文件表中占一个位置,文件表默认大小为1024(可以打开1024个文件)。

文件表中的每一个指针都指向一个文件的结构体,里面有文件打开信息,使用量(状态),inode和文件偏移量。每一个文件都有一个inode,它包含了文件详细信息。

进程开始后会有三个文件默认被打开:标准输入(stdin) 0,标准输出(stdout) 1,标准错误输出(stderr) 2;这三个文件被存在文件表中


文件操作

文件操作分三步:

  1. 打开文件

  1. 读/写

  1. 关闭文件

文件放在磁盘上,可以永久存储,由内核管理文件(文件系统)。

打开文件需要文件名,r/w,(权限);


写(文件描述符,“数据”,大小)

 #include<stdio.h>
 #include<stdlib.h>
 #include<unistd.h>
 #include<string.h>
 #include<fcntl.h>
int main()
{   
    int fd = open("a.txt",O_WRONLY|O_CREAT,0600);//打开,权限0600第一个0是占位符
     printf("fd = %d\n",fd);
  
     write(fd,"hello",5);//写
   
     close(fd);//关闭
   
     exit(0);
}

因为三个默认文件把012占用了,所以这个输出文件描述符为3

1表示屏幕标准输入,可以直接向屏幕上写数据

write(1,"hello",5);

读(文件描述符,读到的位置,大小)

int fd = open("a.txt",O_RDONLY);     
if(fd==-1)//打开失败
{
    printf("open a.txt err\n");
}
char buff[128]={0};//申请空间
int n = read(fd,buff,127);//期望读127个字符,但因为只有hello五个字符,所 以只读五个
printf("n=%d,buff=%s\n",n,buff);
close(fd);
exit(0);

如果一次读不完,需要读多次到文件末尾,当某一次读到0个字节时,文件内容读完,即n=0;每次读都会接着上一次的位置继续读。


应用:复制文件

复制文件就是一个文件一直读,另一个文件一直写。

int main()
{
//打开文件
    int fdr = open("passwd",O_RDONLY);
    int fdw = open("newpasswd",O_WRONLY|O_CREAT,0600);
    if(fdr==-1||fdw==-1)
    {
        printf("open file err\n");
        exit(0);
    }
//读、写
    char buff[1024]={0};
    int n=0;
    while((n=read(fdr,buff,1024))>0)    
    {
       write(fdw,buff,n);
    }
//关闭文件
    close(fdr);
    close(fdw);
 
    exit(0);

}

复制成功:

其他方法

可以将需要复制的文件名作为参数传入主函数

char* filename=argv[1];
char* newfilename = argv[2];
int fdr = open(filename,O_RDONLY);
int fdw = open(newfilename,O_WRONLY|O_CREAT,0600);

运行时输入./main passwd newpasswd

也可以完成上面的复制。


父、子进程读同一文件

当先打开文件再复制进程,父、子进程会共享这份文件(都读这一份),读的偏移量会相互影响。

int main()
{
    int fd = open("a.txt",O_RDONLY);
    if(fd==-1)//文件打开失败
    {
        printf("open file a.txt faild\n");
        exit(0);
    }
    pid_t pid = fork();
    if(pid==-1)//复制进程失败
    {   
        printf("fork err\n");
        exit(0);
    }   
    if(pid==0)//子进程执行读
    {   
        char buff[128]={0};
        read(fd,buff,1);
        printf("child read:%s\n",buff);
        sleep(1);
        read(fd,buff,1);
        printf("child read:%s\n",buff);
    }   
    else//父进程执行读
    {
        char buff[128]={0};
        read(fd,buff,1);
        printf("parent read:%s\n",buff);
        sleep(1);
        read(fd,buff,1);
        printf("parent read:%s\n",buff);
    }

    close(fd);
    exit(0);
}

但当先复制进程再打开文件读,子进程和父进程是各自读各自的

int main()
{
    pid_t pid = fork();//复制进程
    if(pid==-1)
    {   
        printf("fork err\n");
        exit(0);
    }   
    int d = open("a.txt",O_RDONLY);//打开文件
    if(fd==-1)
    {   
        printf("open file a.txt faild\n");
        exit(0);
    }   
    if(pid==0)
    {   
        char buff[128]={0};
        read(fd,buff,1);
        printf("child read:%s\n",buff);
        sleep(1);
        read(fd,buff,1);
        printf("child read:%s\n",buff);
    }   
    else

    {
        char buff[128]={0};
        read(fd,buff,1);
        printf("parent read:%s\n",buff);
        sleep(1);
        read(fd,buff,1);
        printf("parent read:%s\n",buff);
    }

    close(fd);
    exit(0);
}

因为文件打开后文件描述符存放在文件表中,当进程复制时,PCB会先被复制一份,文件表会随着PCB一起复制

当先打开文件,再复制进程,进程被复制后,父、子进程文件表中共用一个文件文件表,共享文件及其偏移量。

当先复制进程再打开文件,这两个进程都会单独打开一个,不再共享。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曦樂~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值