Linux的系统调用

一、系统调用(API)

    系统调用就是操作系统提供的一些功能给程序员使用,这些功能已经被封装成C函数的形式,但它们不是标准C函数的一部分

    一般应用程序运行在用户态(使用的是0~3G的虚拟内存),系统调用时工作在内核态,使用的是(3~4G的虚拟内存)

    常用的标准库的函数,绝大部分时间运行在用户态,底层偶尔也会调用系统进入内核态

二、一切皆文件

    UNIX/Linux 为操作方便把所有的服务、设备等内容都抽象成了文件的形式,闭关提供了一套简单而统一的接口,这部分接口就被称为系统文件IO

    也就是说UNIX/Linux能把任何对象都当做文件处理,以文件形式访问

    文件分类:

    

        普通文件          -      包括纯文本文件、二进制文件、各种压缩文件

        目录文件          d      类似Windows文件夹(必须要有执行权限才能进入)

        块设备文件        b     保存大块数据的设备,例如硬盘

        字符设备文件      c    例如键盘、鼠标等

        链接文件          l    类似Windows的快捷方式

        管道文件          p    

        Socket文件        s    通常用于网络数据链接

三、文件相关的系统调用

    #include <sys/types.h>

       #include <sys/stat.h>

       #include <fcntl.h>

       int open(const char *pathname, int flags);

       功能:打开文件

       pathname:文件的路径

       flags:打开文件的方式

        O_RDONLY        只读

        O_WRONLY        只写

        O_RDWR          读写

        O_APPEND        追加,文件位置指针在末尾

        O_CREAT         文件不存在则创建

        O_EXCL          文件存在则创建失败

        O_TRUNC         文件存在则清空

        返回值:文件描述符,类似于标准库中的FILE*,代表了一个打开的文件,成功返回非负数,失败返回-1

       int open(const char *pathname, int flags, mode_t mode);

        功能:创建文件

        pathname:文件的路径

       flags:打开文件的方式,只能写O_CREAT

       mode:权限掩码    0644 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH

            S_IRWXU 00700   拥有者  读写执行权限

            S_IRUSE 00400   拥有者  读权限

            S_IWUSE 00200   拥有者  写权限

            S_IXUSE 00100   拥有者  执行权限

            S_IRWXG 00070   同组    读写执行权限

            S_IRGRP 00040   同组    读权限

            S_IWGRP 00020   同组    写权限

            S_IXGRP 00010   同组    执行权限

            S_IRWXO 00007   其它    读写执行权限

            S_IROTH 00004   其它    读权限

            S_IWOTH 00002   其它    写权限

            S_IXOTH 00001   其它    执行权限

       int creat(const char *pathname, mode_t mode);

        功能:创建文件

        mode: 同open的mode

        返回值:文件描述符


 

练习1:

    测试fopen的打开方式与open的对应关系 strac./a.out

        out

        w           O_WRONLY|O_CREAT|O_TRUNC, 0666

        w+          O_RDWR|O_CREAT|O_TRUNC, 0666

        r           O_RDONLY

        r+          O_RDWR

        a           O_WRONLY|O_CREAT|O_APPEND, 0666

        a+          O_RDWR|O_CREAT|O_APPEND, 0666

#include <unistd.h>

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

功能:把内存中的数据写入到文件中

fd:文件描述符,也就是open的返回值

buf:待写入的内存首地址

count:要写入的字节数

返回值:成功写入的字节数


 

#include <unistd.h>

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

功能:从文件中读取数据到内存中

fd:文件描述符,也就是open的返回值

buf:数据存储的内存首地址

count:想要读取的字节数

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

#include <unistd.h>

int close(int fd);

功能:关闭文件

返回值成功返回0,失败返回-1


 

练习2:

    分别用标准IO和系统IO来写入100万个整数写入到文件中,测试谁更快,为什么

    直接使用标准IO比系统IO写入的速度更快,因为标准IO有缓冲区机制,在写入数据时,并不是直接调用系统IO,而是先把缓冲区填满,然后再调用系统IO把缓冲区中的数据一并写入文件,提供读写速度

    如果也给系统IO增加一个缓冲区机制,则系统IO运行速度会比标准IO速度要快

    速度:

        标准IO>系统IO

        系统IO+缓冲区>标准IO

四、随机读写

    每个打开的文件都有一个记录着读写位置的文件位置指针,对文件的读写操作都从该指针指向的位置进行,位置指针会随着读写的操作而自动移动

    一个打开的文件,位置指针指向开头,若使用O_APPEND,则在文件末尾

    如果想要随意读取文件中的任意位置的数据,可以通过调整位置指针来实现

    //标准IO

    int fseek(FILE *stream, long offset, int whence);

    返回值:成功0   失败-1

    //系统IO

    off_t lseek(int fd, off_t offset, int whence);

    fd:文件描述符

    offset:偏移量

    whence:基础位置

            SEEK_SET        文件开头

            SEEK_CUR        当前位置

            SEEK_END        文件末尾

    返回值:调整后文件位置指针所在的位置

    如何在越过文件末尾的位置写入数据,将在中间形成空洞,空洞会被计算入文件大小中,但是不占用磁盘空间

五、系统IO读写文本文件

    系统IO没有类似fprintf/fscanf函数的,因此不能直接读写文本文件

    写文本文件:

        对象    sprintf 转换成字符串,然后再通过write写入文件

    读取文本文件

        read字符串形式读取,然后再用sscanf解析转换成对应的数据使用

六、文件描述符

    1、非负整数,代表一个打开的文件

    2、通过系统调用(open\creat)返回,也可以被内核空间引用

    3、它代表了一个内核对象(类似于FILE对象),因为内核不能暴露该对象的地址,因此通过它来表示

    4、内核中有一张表记录了所有打开的文件对象,文件描述符就是访问这张表的下标,相当于访问文件对象的凭证

        内核中有三个默认打开的文件描述符

            0   标准输入  stdin 

            1   标准输出  stdout

            2   标准错误  stderr

    

    文件描述符的复制:

    int dup(int oldfd);

    功能:复制一个已经打开的文件描述符

    返回值:返回一个没有用过的最小的文件描述符

    int dup2(int oldfd, int newfd);

    功能:复制成一个指定的文件描述符

    newfd:想要复制成的文件描述符,如果newfd已经打开,会先关闭,再复制

    返回值:返回newfd的值

    

    注意:复制成功后,相当于两个不同的文件描述符对应同一个打开的文件

    练习3:使用系统IO实现一个带覆盖测试的cp命令

            ./cp src dest

            目标文件存在,是否覆盖(y/n)?


 

    

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值