Linux文件,目录IO类系统调用总结与示例

news2024/11/25 2:58:37

tags: C Syscall Linux

写在前面

无论是做网络编程还是系统编程, 逃不开的一个内容就是C系统调用的学习, 正如C++的STL一样, 学习OS也有如下的三步骤:

  1. 会使用: 熟悉API
  2. 懂原理: 分析源码
  3. 写扩展: 实际开发

现在就来熟悉一下系统调用吧. 环境Ubuntu x86_64.

源码部分也参考了apue以及Linux/UNIX系统编程手册.

预备知识

什么是系统调用

  1. 系统调用将处理器从用户态切换到核心态, 以便让CPU访问受到保护的内核内存数据.
  2. 其组成是固定的, 每一个系统调用都由唯一一个数字来标识.

程序运行四区

截屏2023-02-04 00.37.08.jpg

非常重要, 全图背诵.

标准文件描述符

文件描述符用途POSIX名称stdio流
0标准输入STDIN_FILENOstdin
1标准输出STDOUT_FILENOstdout
2标准错误STDERR_FILENOstderr

针对stdout调用freopen()函数后,无法保证stdout变量值仍然为1。

常用头文件

头文件包括的常用函数/常量作用
sys/types.h类型定义
sys/stat.h状态定义
stdio.hprintf,fprintf标准I/O函数
stdlib.hmalloc,free标准库函数
unistd.hsleep,部分系统调用
errno.h错误状态码
string.hmemset,strcpy字符创相关操作
(堆内存分配与初始化)
limits.hINT_MAX系统限制
fcntl.hfcntl,文件I/O函数(高级)

文件I/O

文件访问模式

常用的文件访问模式如下表.

访问模式描述访问模式描述
O_RDONLY只读打开O_CREAT不存在则创建
O_WRONLY只写打开O_TRUNC截断已有文件
(长度置为0)
O_RDWR读写打开O_APPEND文件尾部追加

备注:

  1. 调用open()时, O_RDONLY、O_WRONLY和O_RDWR标志在flags参数中不能同时使用,只能指定其中一种
  2. O_TRUNC: 如果文件已经存在且为普通文件,那么将清空文件内容,将其长度置0。在Linux下使用此标志,无论以读、写方式打开文件,都可清空文件内容(在这两种情况下,都必须拥有对文件的写权限)

权限位

权限位st_mode含义八进制值英文注记
S_IRUSR用户读4READ USER
S_IWUSR用户写2WRITE USER
S_IXUSR用户执行1EXEC USER
S_IRGRP组读4READ GROUP
S_IWGRP组写2WRITE GROUP
S_IXGRP组执行1EXEC GROUP
S_IROTH其他用户读4READ OTHER
S_IWOTH其他用户写2WRITE OTHER
S_IXOTH其他用户执行1EXEC OTHER

例如常用的可执行文件权限位: 755, 就对应了rwx-r-xr-x, 而默认创建目录的权限位为:

open: 创建文件

fd = open(pathname, flags, mode) 函数打开pathname所标识的文件,并返回文件描述符,用以在后续函数调用中指代打开的文件。如果文件不存在,open()函数可以创建之,这取决于对位掩码参数flags的设置。

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

void error_handling(char* msg);

int fd;
void t1() {
    // create and write
    char buf[] = "Let's go!";

    fd = open("data", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
    if (fd == -1) error_handling("open() error");
    printf("file descripter: %d\n", fd);

    if (write(fd, buf, sizeof(buf)) == -1) error_handling("write() error");

    close(fd);
}
void t2() {
    // append to log
    char buf[] = "abc\n";
    fd = open("log", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
    if (fd == -1) error_handling("open() error");
    printf("file descripter: %d\n", fd);

    if (write(fd, buf, sizeof(buf)) == -1) error_handling("write() error");
    close(fd);
}


int main(int argc, char* argv[]) {
    t1();
    t2();
    return 0;
}


void error_handling(char* msg) {
    fputs(msg, stderr);
    fputc('\n', stderr);
    /* printf("aa\n"); */
    exit(1);
}

read: 读出流

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

void t1() {
    int fd = open("data", O_RDONLY);
    char buf[100];
    read(fd, buf, 10);
    printf("buf=%s\n", buf); // buf=Let's go!

    close(fd);
}
int main(int argc, char *argv[]) {
    t1();
    return 0;
}

write: 写入流

例子见open().

close: 关闭文件

lseek: 改变文件偏移量

对于每个打开的文件,系统内核会记录其文件偏移量,有时也将文件偏移量称为读写偏移量或指针。文件偏移量是指执行下一个read()或write()操作的文件起始位置,会以相对于文件头部起始点的文件当前位置来表示。文件第一个字节的偏移量为0。

文件打开时,会将文件偏移量设置为指向文件开始,以后每次read()或write()调用将自动对其进行调整,以指向已读或已写数据后的下一字节。因此,连续的read()和write()调用将按顺序递进,对文件进行操作。
针对文件描述符fd参数所指代的已打开文件,lseek()系统调用依照offset和whence参数值调整该文件的偏移量。

offset参数指定了一个以字节为单位的数值。(SUSv3规定off_t数据类型为有符号整型数。)whence参数则表明应参照哪个基点来解释offset参数,应为下列其中之一:

  • SEEK_SET: 将文件偏移量设置为从文件头部起始点开始的offset个字节
  • SEEK_CUR: 相对于当前文件偏移量,将文件偏移量调整offset个字节.
  • SEEK_END: 将文件偏移量设置为起始于文件尾部的offset个字节。也就是说,offset参数应该从文件最后一个字节之后的下一个字节算起.
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

void t1() {
    int fd = open("data", O_WRONLY, S_IWUSR);
    int cur = lseek(fd, 0, SEEK_CUR);
    printf("cur seek = %d\n", cur);
    cur = lseek(fd, 2, SEEK_SET);
    printf("cur seek = %d\n", cur);
}

int main(int argc, char *argv[]) {
    t1();
    return 0;
}

文件信息

#include <stdio.h>
#include <time.h>
#include <sys/stat.h>

int main(int argc, char *argv[]) {
    struct stat sb;
    if (stat("data", &sb) == -1) fprintf(stderr, "stat-error");
    printf("size=%ld\n", sb.st_size);
    printf("mode=%u\n", sb.st_mode);
    printf("uid=%u\n", sb.st_uid);
    printf("gid=%u\n", sb.st_gid);
    printf("hard link number=%ld\n", sb.st_nlink);
    putchar('\n');
    printf("dev-id=%ld\n",sb.st_dev);
    printf("rdev-id=%ld\n", sb.st_rdev);
    printf("i-node=%ld\n", sb.st_ino);
    printf("block-size=%ld\n", sb.st_blksize);
    printf("blocks=%ld\n", sb.st_blocks);
    putchar('\n');
    printf("last access time=%s", ctime(&sb.st_atime));
    printf("last modify time=%s", ctime(&sb.st_mtime));
    printf("last status change time=%s\n", ctime(&sb.st_ctime));
    return 0;
}
/* size=10 */
/* mode=33152 */
/* uid=1001 */
/* gid=1001 */
/* hard link number=1 */
/*  */
/* dev-id=64513 */
/* rdev-id=0 */
/* i-node=1212099 */
/* block-size=4096 */
/* blocks=8 */
/*  */
/* last access time=Thu Feb  9 17:42:47 2023 */
/* last modify time=Sun Feb  5 01:19:56 2023 */
/* last status change time=Sun Feb  5 01:19:56 2023 */ 

目录I/O

mkdir: 创建目录

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

// rw-r--r--
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
// rwxrwxr-x
#define DIR_MODE (FILE_MODE | S_IXUSR | S_IWGRP | S_IXGRP | S_IXOTH)

int main(int argc, char *argv[]) {
    mkdir("new_dir", DIR_MODE);
    return 0;
}

getpwd: 获取当前目录

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


int main(int argc, char *argv[]) {
    char *ptr;
    size_t size = 100;
    ptr = (char *)malloc(size);

    getcwd(ptr, size);
    printf("cwd = %s\n", ptr); // cwd = /home/zorch/code/c_cpp_code/syscall/dirio
    return 0;
}

chdir: 更改当前目录

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


int main(int argc, char *argv[]) {
    char *ptr;
    size_t size = 100;
    ptr = (char *)malloc(size);
    chdir("/usr/local/lib");

    getcwd(ptr, size);
    printf("cwd = %s\n", ptr); // cwd = /usr/local/lib

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/333581.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023抓住这些风口,让你的服装生意一路狂飙!

如今正是消费回暖的大好时机&#xff0c;想要趁着行情回升大展身手的服装商户们&#xff0c;抓住2023的这些风口&#xff0c;生意一路狂飙不是梦&#xff01;风口1&#xff1a; T 恤和运动衫全球纺织信息透露&#xff0c;在全球范围内&#xff0c;T 恤和运动衫的市场规模将在 2…

骑车不戴头盔识别检测系统 Tesnorflow

骑车不戴头盔识别检测系统通过GPU深度学习技术&#xff0c;骑车不戴头盔识别检测对行驶在马路上的骑电动摩托车等未戴头盔的行为进行抓拍&#xff0c;不经过人为干预自动对上述违规行为进行自动抓拍识别。骑车不戴头盔识别检测系统技术上采用 TesnorflowTensorRT推理组合&#…

Qt学习笔记

文章目录一、C指针函数驼峰命名法、下划线命名法编程报错二、C三、Qt语法Qt历史、Qt应用Qt特色快捷键Qt类的族谱QWidgetQPushButtonQDebug对象树Qt窗口坐标信号和槽Qt自带的信号的槽自定义的信号和槽Qt4版本 vs Qt5版本 的connect写法函数指针解决重载问题拓展类型转换QString …

Minikube vs. kind vs. k3s vs k3d vs MicroK8s

文章目录1. minikube2. k3s3. k3d4. Kind5. MicroK8s1. minikube minikube 是一个 Kubernetes SIG 项目&#xff0c;已经启动三年多了。它采用生成虚拟机的方法&#xff0c;该虚拟机本质上是一个单节点 K8s 集群。由于支持大量管理程序&#xff0c;它可以在所有主要操作系统上…

项目管理基础

项目的特点 项目是为提供独特产品、服务或成果所做的临时性努力 临时性&#xff08;一次性&#xff0c;指项目有明确的开始时间和结束时间&#xff09;独特性逐步完善-渐进明细资源约束目的性 项目的三重制约&#xff1a; 成本 质量 时间 其次还有范围 目标&#xff1a;多快…

FPGA时序约束与分析 --- 实例教程(1)

注意&#xff1a; 时序约束辅助工具或者相关的TCL命令&#xff0c;都必须在 open synthesis design / open implemention design 后才能有效运行。 1、时序约束辅助工具 2、查看相关时序信息 3、一般的时序约束顺序 1、 时序约束辅助工具&#xff08;1&#xff09;时序约束编辑…

操作系统的奋斗(三)内存管理

第三章 内存管理3.1内存管理概念3.1.1 内存管理的基本原理和要求&#xff08;1&#xff09;内存管理的主要功能3.1.2 覆盖和交换&#xff08;1&#xff09;覆盖&#xff08;2&#xff09;交换3.1.3 连续分配管理方式&#xff08;1&#xff09;单一连续分配&#xff08;2&#x…

【Spring源码】23. 执行初始化逻辑:initializeBean()

进入initializeBean()先检查是否有安全管理器&#xff0c;如果有就以特权方式执行回调bean中Aware接口方法invokeAwareMethods()invokeAwareMethods()这个方法处理了3个Aware&#xff08;更多关于Aware的内容可移步至那些Aware们&#xff09;BeanNameAwareBeanClassLoaderAware…

json文件在faster_rcnn中从测试到训练 可行性

1.确认任务 经过mydataset文件处理后 - > 在train_res50_fpn文件内应用 # load train data set # VOCdevkit -> VOC2012 -> ImageSets -> Main -> train.txt train_dataset VOCDataSet(VOC_root, "2012", data_transform["train"], &…

Python 异步: 使用和查询任务(8)

任务是异步程序的货币。在本节中&#xff0c;我们将仔细研究如何在我们的程序中与它们交互。 1. 任务生命周期 异步任务具有生命周期。首先&#xff0c;任务是从协程创建的。然后安排在事件循环中独立执行。在某个时候&#xff0c;它会运行。 在运行时它可能会被挂起&#xff0…

舆情监测方案主体需求,TOOM舆情监测预警应对处置方案

舆情监测预警是一种通过预先设定的告警机制&#xff0c;在发生重要事件或异常情况时及时通知相关人员的舆情监测方式。它旨在帮助企业和组织及时了解舆情变化&#xff0c;并采取必要的应对措施&#xff0c;舆情监测方案主体需求&#xff0c;TOOM舆情监测预警应对处置方案。 一…

在Unity中管理材质

Shader和Material的关系 Shader能够设置游戏物体的颜色或者能够通过材质来配置颜色。实际上&#xff0c;一个shader能够让许多物体看起来像是完全不同的物质。 Shader和材质作为一个整体工作&#xff1a;Shader定义了表面看起来可以像哪些东西&#xff0c;材质让表面真正看起来…

【手写 Vuex 源码】第一篇 - Vuex 的基本使用

一&#xff0c;前言 本篇开始&#xff0c;进入 vuex 源码学习&#xff0c;本篇主要介绍一下内容&#xff1a; 创建 vuex 源码项目&#xff1b;介绍 vuex 的基本使用&#xff1b; 二&#xff0c;创建 vuex 源码项目 1&#xff0c;使用 vue-cli 创建 vue2.x 脚手架 vue creat…

shell脚本(语法)

一、什么是shell脚本 1.1、shell 的两层含义&#xff1a;既是一种应用程序,又是一种程序设计语言 1.1.1、shell是一种应用程序 交互式地解释、执行用户输入的命令&#xff0c;将用户的操作翻译成机器可以识别的语言&#xff0c;完成相应功能称之为 shell 命令解析器。 shell 是…

阳离子交换树脂排钾,选择性吸附钾离子

Tulsimer T-42特级凝胶型强酸性阳离子交换树脂&#xff0c;适用于超纯水系统的混床用阳离子交换树脂 Tulsimer T-42是特级强酸型离子交换树脂&#xff0c;氢 H/钠 Na阳离子交换树脂&#xff0c; 是一款有较的交换容量 ,并同时拥有物理及化学稳定品质。可应用于汽电共生发电厂冷…

excel操作技巧:聊聊关于打印的一些事儿

在之前的学习中&#xff0c;小编给小伙伴们带来了许多关于Excel操作的小技巧&#xff0c;不过最近很多小伙伴在打印上又犯了难题&#xff0c;倒在了最后一步上&#xff0c;实在是亏得很。今天小编就来给大家讲讲打印的那些难事儿&#xff01;难题一&#xff1a; 多列数据打印不…

【Unity】Tomcat 部署项目(3种方式)

一、将Unity WebGL包丢进webapps这是最简单粗暴的方式&#xff1a;将Unity WebGL包丢进tomcat/webapps目录即可。无需修改任何配置文件即可完成部署。使用tomcat10与Unity Pong Game包来做测试。①启动tomcat②将Unity Pong Game包丢进webapps目录浏览器直接访问&#xff1a;lo…

HTTP和HTTPS协议

HTTP协议 HTTP协议是一种应用层的协议&#xff0c;全称为超文本传输协议。 URL URL值统一资源定位标志&#xff0c;也就是俗称的网址。 协议方案名 http://表示的就是协议方案名&#xff0c;常用的协议有HTTP协议、HTTPS协议、FTP协议等。HTTPS协议是以HTTP协议为基础&#…

java面经汇总

Java基础 什么是字节码&#xff1f; jvm可以理解的代码&#xff08;.class文件&#xff09; Java代码从源代码到运行过程&#xff1a; java代码 -> javac编译器->.class字节码文件 -> 解释器&JIT&#xff08;运行时编译器&#xff09;->机器码 JIT编译器会将热…

球面坐标系下的三重积分

涉及知识点 三重积分球面坐标系点火公式一些常见积分处理手法 球面坐标系定义 球面坐标系由方位角φ\varphiφ、仰角θ\thetaθ和距离rrr构成 直角坐标系(x,y,z)(x,y,z)(x,y,z)到球面坐标系的(r,φ,θ)(r,\varphi,\theta)(r,φ,θ)的转化规则如下&#xff1a; {xrsin⁡φco…