Linux高级编程_27_系统调用

文章目录

  • 系统调用
    • 函数分类
    • 系统编程概述
    • 系统调用概述
      • **类UNIX系统的软件层次**
    • 用户态和内核态
    • 系统调用与库函数的关系
    • 文件操作符
      • 概述
      • 文件磁盘权限
    • 系统调用之文件操作
      • open:打开文件
      • close:关闭文件
      • write:写入
      • read:读取
    • 文件状态
      • fcntl 函数
      • stat 函数
    • st_mode的值
        • 示例 1:
        • 示例 2:只写和追加
        • 示例 3: 写文件
        • 示例 4: 读文件
    • 文件夹操作
    • opendir
    • readdir
        • 示例:遍历文件夹
    • closedir

系统调用

函数分类

  • 库函数
    • 系统提供的,不能直接访问内核的 如fopen
  • 系统调用
    • 系统提供的,可以直接访问内核 如 open
  • 自定义函数
    • 自己编写的

注意

man命令:查看帮助手册

  • 章节1 查命令 例: man 1 ls

  • 章节2 系统调用 man 2 open

  • 章节3 库函数 man 3 fopen

系统编程概述

操作系统的职责

   操作系统用来管理所有的资源,并将不同的设备和不同的程序关联起来。

什么是 Linux 系统编程

  在有操作系统的环境下编程,并使用操作系统提供的系统调用及各种库,对系统资源进行访问。学会了C 语言再知道一些使用系统调用的方法,就可以进行Linux 系统编程了,

简单说 就是使用软件操控系统硬件以及资源 比如 灯亮…

系统调用概述

系统调用是操作系统提供给用户程序的一组“特殊”函数接口。

类UNIX系统的软件层次

在这里插入图片描述

在这里插入图片描述

用户态和内核态

引入

>	CPU 指令是可以直接操作硬件的,要是因为指令操作的不规范,造成的错误是会影
响整个 计算机系统 的。好比你写 一个程序,但是因为你对 硬件操作 不熟悉,出现
问题,那么影响范围是多大?是整个计算机系统,操作系统内核、及其其他所有正在运
行的程序,都会因为你操作失误而受到不可挽回的错误,那么你只有重启整个计算机才
行
>	而对于 硬件的操作 是非常复杂的,参数众多,出问题的几率相当大,必须及其谨
慎的进行操作,这对于个人开发者来说是个艰巨的任务,同时个人开发者在这方面也是
不被信任的。所以 操作系统内核 直接屏蔽了个人开发者对于硬件操作的可能.
>   这方面 系统内核 对 硬件操作 进行了封装处理,对外提供标准函数库,操作更简
单、更安全。比如 我们要打开一个文件,C标准函数库中对应的是fopen(),其内部封
装的是内核中的系统函数open()
>	因为这个需求,硬件设备商直接提供了硬件级别的支持,做法就是对 CPU 指令设置了
权限,不同级别的权限可以使用的 CPU 指令是有限制的。以 Inter CPU 为例,
Inter 把 CPU 指令操作的权限划为4级:ring 0ring 1ring 2ring 3
>	其中 ring 0 权限最高,可以使用所有 CPU 指令,ring 3 权限最低,仅能使用
常规 CPU 指令,这个级别的权限不能使用访问硬件资源的指令,比如 IO 读写、网卡
访问、申请内存都不行,都没有权限	
>	Linux 系统内核采用了:ring 0 和 ring 3 这2个权限
>	ring 0:内核态,完全在 操作系统内核 中运行,由专门的 内核线程 在 CPU 中
执行其任务
>	ring 3:用户态,在 应用程序 中运行,由 用户线程 在 CPU 中执行其任务
>	Linux 系统中所有对硬件资源的操作都必须在 内核态 状态下执行,比如 IO 的
读写,网络的操作

区别:

>	1,用户态的代码必须由 用户线程 去执行、内核态的代码必须由 内核线程 去执行
>	2,用户态、内核态 或者说 用户线程、内核线程 可以使用的资源是不同的,尤体现在
内存资源上。Linux 内核对每一个进程都会分配 4G 虚拟内存空间地址用户态: --> 只能操作 0-3G 的内存地址内核态: --> 0-4G 的内存地址都可以操作,尤其是对 3-4G 的高位地址必须由
内核态去操作,因为所有进程的 3-4G 的高位地址使用的都是同一块、专门留给 系统
内核 使用的 1G 物理内存>	3.所有对 硬件资源、系统内核数据 的访问都必须由内核态去执行

如何切换内核态?

​ 通过软件中断

软件中断与硬件中断

> 软件中断软件中断是由软件程序触发的中断,如系统调用、软中断、异常等。软件中断不是硬件设备触发的,而是由软件程序主动发起的,一般用于系统调用、进程切换、异常处理等任务。软件中断需要在程序中进行调用,其响应速度和实时性相对较差,但是具有灵活性和可控性高的特点。如程序中出现的内存溢出,数组下标越界等> 硬件中断硬件中断是由硬件设备触发的中断,如时钟中断、串口接收中断、外部中断等。当硬件设备有数据或事件需要处理时,会向CPU发送一个中断请求,CPU在收到中断请求后,会立即暂停当前正在执行的任务,进入中断处理程序中处理中断请求。硬件中断具有实时性强、可靠性高、处理速度快等特点。如当点击按钮扫描系统高低电频时等

系统调用与库函数的关系

在这里插入图片描述

注意:

系统调用是需要时间的,程序中频繁的使用系统调用会降低程序的运行效率。当运行内核代码时,CPU工作在内核态,在系统调用发生前需要保存用户态的栈和内存环境,然后转入内核态工作。系统调用结束后,又要切换回用户态。这种环境的切换会消耗掉许多时间。

文件操作符

概述

>	文件描述符是一个非负整数,代表已打开的文件。每一个进程都会创建一张文件描述符表 记录的是当前进程打开的所有文件描述符。每一个进程默认打开三个文件描述符:0(标准输入设备scanf)1(标准输出设备printf)2(标准错误输入设备perror)。新打开的文件描述符 为最小可用文件描述符

在这里插入图片描述

扩展

ulimit是一个计算机命令,用于shell启动进程所占用的资源,可用于修改系统资源限
制。使用ulimit命令用于临时修改资源限制,如果需要永久修改需要将设置写入配置文
件/etc/security/limits.conf。ulimit -a 查看open files打开的文件最大数。ulimit -n 最大数 设置open files打开的文件最大数。

文件磁盘权限

在这里插入图片描述

第一位d 说是 文件还是文件夹
2~4位说明	所有者权限
5~7位说明	同组用户权限
8~10位说明其他用户权限
r   4
w   2
x   1
只读   	4 
只写       2  
只执行     1
可读可写    6
可读可执行	5
可读可写可执行  7

系统调用之文件操作

open:打开文件

所需头文件

  • #include <sys/types.h>
  • #include <sys/stat.h>
  • #include <fcntl.h>

函数

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

参数

pathname:  打开的文件地址
flags:     代码操作文件的权限必选项O_RDONLY 	以只读的方式打开O_WRONLY 	以只写的方式打开O_RDWR		以可读、可写的方式打开可选项O_CREAT 	文件不存在则创建文件,使用此选项时需使用 mode 说明文件的权限O_EXCL 		如果同时指定了 O_CREAT,且文件已经存在,则打开,如果文件不存在则新建O_TRUNC 	如果文件存在,则清空文件内容O_APPEND 	写文件时,数据添加到文件末尾O_NONBLOCK 	对于设备文件, 以 O_NONBLOCK 方式打开可以做非阻塞I/Omode:文件在磁盘中的权限格式:0dddd的取值:4(可读),2(可写),1(可执行)第一个d:所有者权限第二个d:同组用户权限第三个d:其他用户权限如果需要可读可写就是6,可读可执行5等如:0666:所有者可读可写,同组用户可读可写,其他用户可读可写0765:所有者可读可写可执行,同组用户可读可写,其他用户可读可执行返回值:成功:得到最小可用的文件描述符失败:-1

技巧:

  • 操作已有文件使用两参
  • 新建文件使用三参

close:关闭文件

0 代表标准输入(stdin),

1 代表标准输出(stdout),

2 代表标准错误输出(stderr),

例如: close(0);表示 标准输入禁用

所需头文件#include<unistd.h>
函数int close(int fd);
参数关闭的文件描述符返回值成功:0失败:-1,并设置errno

write:写入

所需头文件#include <unistd.h>
函数ssize_t write(int fd, const void *buf, size_t count);
参数fd:写入的文件描述符buf:写入的内容首地址count:写入的长度,单位字节
返回值成功:返回写入的内容的长度,单位字节失败:-1	

read:读取

所需头#include <unistd.h>
函数ssize_t read(int fd,void *buf,size_t count);
参数:fd:文件描述符buf:内存首地址count:读取的字节个数
返回值:成功:实际读取到的字节个数失败:-1

读取完的依据:

返回值 小于 设定的每次读取的字节数

文件状态

fcntl 函数

作用:针对已存在的文件描述符设置阻塞状态
语法:所需头文件:#include <unistd.h>#include <fcntl.h>函数:int fcntl(int fd, int cmd, ... /* arg */);功能:改变已打开的文件性质,fcntl 针对描述符提供控制。参数:fd:操作的文件描述符cmd:操作方式arg:针对 cmd 的值,fcntl 能够接受第三个参数 int arg   返回值:成功:返回某个其他值失败:-1                
fcntl 函数有 5 种功能:1) 复制一个现有的描述符(cmd=F_DUPFD)2) 获得/设置文件描述符标记(cmd=F_GETFD 或 F_SETFD)3) 获得/设置文件状态标记(cmd=F_GETFL 或 F_SETFL)4) 获得/设置异步 I/O 所有权(cmd=F_GETOWN 或 F_SETOWN)5) 获得/设置记录锁(cmd=FGETLK, F_SETLK 或 F_SETLKW)               

stat 函数

作用:
获取文件状态信息
所需头

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>函数
int stat(const char *path, struct stat *buf);
int lstat(const char *pathname,struct stat *buf);参数
1参:文件地址
2参:保存文件信息的结构体返回值
0:成功
-1:失败注意:当文件是一个符号链接时lstat返回的是该符号链接本身的信息。stat返回的是该链接指向的文件的信息。【重要】struct stat {dev_t st_dev; //文件的设备编号ino_t st_ino; //节点mode_t st_mode; //文件的类型和存取的权限nlink_t st_nlink; //连到该文件的硬连接数目,刚建立的文件值为 1uid_t st_uid; //用户 IDgid_t st_gid; //组 IDdev_t st_rdev; //(设备类型)若此文件为设备文件,则为其设备编号off_t st_size; //文件字节数(文件大小)blksize_t st_blksize; //块大小(文件系统的 I/O 缓冲区大小)blkcnt_t st_blocks; //块数time_t st_atime; //最后一次访问时间time_t st_mtime; //最后一次修改时间time_t st_ctime; //最后一次改变时间(指属性)
};   

st_mode的值

在这里插入图片描述

示例 1:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{// O_TRUNC  覆盖清空 O_RDONLY 只读   O_WRONLY 只写  int f01 = open("./a.txt", O_RDONLY | O_WRONLY | O_CREAT | O_TRUNC, 0664);if (f01 < 0){printf("打开失败!\n");return 0;}printf("end \tf01=%d\n", f01); // 3   因为0 1 2 被占用int flag = close(f01);printf("flag = %d\n", flag);if (flag < 0){printf("关闭失败\n");}else{printf("关闭成功\n");}return 0;
}

在这里插入图片描述

示例 2:只写和追加
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char const *argv[])
{// 关闭标准输入流close(0);// 权限是 只写 和追加 方式 打开int fd = open("./a.txt", O_WRONLY | O_APPEND );printf("fd = %d\n",fd); //此时打印的fd是0,证明返回的是最小可用描述符char *str = "你好\n";write(fd, str, strlen(str));close(fd); // 关闭文件return 0;
}
示例 3: 写文件
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char const *argv[])
{char *str  = "hello , 系统调用\n"; // 此处中文占了3字节  但是一般中文占2~4  具体视情况而定//参数1: 写入的文件描述符 //参数2: 写入的内容首地址 //参数3: 写入的长度,单位字节//成功:返回写入的内容的长度,单位字节 失败:-1int t = write(1,str,strlen(str));   // strlen 测长度 不算 \0printf("xxz = %d\n",t);return 0;
}

在这里插入图片描述

示例 4: 读文件
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char const *argv[])
{char str[50] = {0};// 参数一: 文件描述符// 参数二: 内存首地址// 参数三: 读取的字节个数// 返回值: 成功:实际读取到的字节个数   失败:-1read(0, str, 50);  // 0 标准输入printf("num = %s\n",str);return 0;
}

文件夹操作

遍历文件夹很重要

opendir

打开目录

> 作用:打开目录 opendir
所有头文件:#include <sys/types.h>#include <dirent.h>
函数:DIR *opendir(const char *name);
参数:name:目录名
返回值:成功:返回指向该目录结构体指针(DIR *)失败:NULL
DIR:中文名称句柄,其实就是目录的结构体指针

readdir

读取目录

> 作用:		读取目录 
所需头文件#include <dirent.h>
函数struct dirent *readdir(DIR *dirp);
参数:dirp:opendir 的返回值
返回值:成功:目录结构体指针失败:NULL
注意:一次读取一个文件。相关结构体说明:
struct dirent
{ino_t d_ino; // 此目录进入点的 inodeoff_t d_off; // 目录文件开头至此目录进入点的位移signed short int d_reclen; // d_name 的长度, 不包含 NULL 字符unsigned char d_type; // d_type 所指的文件类型char d_name[256]; // 文件名
};d_type说明:DT_BLK 这是一个块设备。(块设备如:磁盘)DT_CHR 这是一个字符设备。(字符设备如:键盘,打印机)DT_DIR 这是一个目录。DT_FIFO 这是一个命名管道(FIFO)。DT_LNK 这是一个符号链接。DT_REG 这是一个常规文件。DT_SOCK 这是一个UNIX域套接字。DT_UNKNOWN 文件类型未知。
示例:遍历文件夹
#include <stdio.h>
#include <string.h>
//   遍历  家目录  文件夹
// 打开文件夹所需头文件
#include <sys/types.h>
#include <dirent.h>
void blDIR(char *dirPATH)
{DIR *d = opendir(dirPATH);   // 打开文件夹//返回指向该目录结构体指针(DIR *)if (d == NULL){printf("打开失败\n");return 0;} // 打开成功 使用递归开始遍历while (1){struct dirent *d2 = readdir(d);if (d2 == NULL){break;}if (d2->d_type == DT_DIR){if (strcmp(d2->d_name,".") == 0 || strcmp(d2->d_name,"..") == 0) {//遇到文件有. 和.. 的 就暂不执行本次循环continue; // 跳出本次循环}char path[500] = {0};//追加操作 将dirent 内容追加到 path尾部strcat(path,dirPATH);  strcat(path,"/");strcat(path,d2->d_name); // printf("=======\n");printf("%s\n",path);blDIR(path);          }else if (d2->d_type == DT_REG) // 类型要是文件{printf("%s\n",d2->d_name);}}closedir(d);// 关闭文件d   
}
int main(int argc, char const *argv[])
{blDIR("/home/xxz/");return 0;
}

closedir

关闭目录

> 作用:关闭目录 closedir
所需头文件#include <sys/types.h>#include <dirent.h>
函数int closedir(DIR *dirp);
参数:dirp:opendir 返回的指针
返回值:成功:0失败:-1

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【优选算法之队列+宽搜/优先级队列】No.14--- 经典队列+宽搜/优先级队列算法

文章目录 前言一、队列宽搜示例&#xff1a;1.1 N 叉树的层序遍历1.2 ⼆叉树的锯⻮形层序遍历1.3 ⼆叉树最⼤宽度1.4 在每个树⾏中找最⼤值 二、优先级队列&#xff08;堆&#xff09;示例&#xff1a;2.1 最后⼀块⽯头的重量2.2 数据流中的第 K ⼤元素2.3 前 K 个⾼频单词2.4 …

数造科技入选中国信通院《高质量数字化转型产品及服务全景图》三大板块

9月24日&#xff0c;2024大模型数字生态发展大会暨“铸基计划”年中会议在北京召开。会上&#xff0c;中国信通院发布了2024年《高质量数字化转型产品及服务全景图&#xff08;上半年度&#xff09;》和《高质量数字化转型技术解决方案&#xff08;上半年度&#xff09;》等多项…

网络编程篇:UDP协议

一 UDP协议格式 16位源端口号&#xff1a;表示数据从哪里来。16位目的端口号&#xff1a;表示数据要到哪里去。16位UDP长度&#xff1a;表示整个数据报&#xff08;UDP首部UDP数据&#xff09;的长度。16位UDP检验和&#xff1a;如果UDP报文的检验和出错&#xff0c;就会直接将…

【Kubernetes】常见面试题汇总(五十三)

目录 118. pod 状态为 ErrlmagePull &#xff1f; 119.探测存活 pod 状态为 CrashLoopBackOff &#xff1f; 特别说明&#xff1a; 题目 1-68 属于【Kubernetes】的常规概念题&#xff0c;即 “ 汇总&#xff08;一&#xff09;~&#xff08;二十二&#xff09;” 。…

MongoDB聚合操作及索引底层原理

目录 链接:https://note.youdao.com/ynoteshare/index.html?id=50fdb657a9b06950fa255a82555b44a6&type=note&_time=1727951783296 本节课的内容: 聚合操作: 聚合管道操作: ​编辑 $match 进行文档筛选 ​编辑 将筛选和投影结合使用: ​编辑 多条件匹配: …

Springboot + netty + rabbitmq + myBatis

目录 0.为什么用消息队列1.代码文件创建结构2.pom.xml文件3.三个配置文件开发和生产环境4.Rabbitmq 基础配置类 TtlQueueConfig5.建立netty服务器 rabbitmq消息生产者6.建立常规队列的消费者 Consumer7.建立死信队列的消费者 DeadLetterConsumer8.建立mapper.xml文件9.建立map…

King3399 SDK(ubuntu文件系统)编译简明教程

该文章仅供参考&#xff0c;编写人不对任务实验设备、人员及测量结果负责&#xff01;&#xff01;&#xff01; 0 引言 文章主要介绍King3399&#xff08;瑞芯微rk3399开发板&#xff0c;荣品&#xff09;官方SDK&#xff08;Ubuntu文件系统&#xff09;编译过程&#xff0c…

【本地免费】SimpleTex 图像识别latex公式

文章目录 相关教程相关文献安装教程 由于mathpix开始收费了&#xff0c;于是本文将介绍一款目前本地免费的SimpleTex工具 相关教程 【超详细安装教程】LaTeX-OCR 图像识别latex公式&#xff08;开源免费&#xff09;_latex图片识别-CSDN博客 相关文献 SimpleTex主页——致力…

Elasticsearch使用Easy-Es + RestHighLevelClient实现深度分页跳页

注意&#xff01;&#xff01;&#xff01;博主只在测试环境试了一下&#xff0c;没有发到生产环境跑。因为代码还没写完客户说不用弄了( •̩̩̩̩&#xff3f;•̩̩̩̩ ) 也好&#xff0c;少个功能少点BUG 使用from size的时候发现存在max_result_window10000的限制&…

薄膜凸起和开裂是同一种应力导致的吗?

知识星球里的学员问&#xff1a;我们产线上薄膜出了质量问题&#xff0c;都一概归结为应力过大。麻烦讲讲应力的种类&#xff0c;以及不同种类的应力会造成哪些薄膜问题&#xff1f; 内应力的种类&#xff1f; 内应力的分类很多&#xff0c;如果我们按作用的效果来分&#xff…

树莓派 AI 摄像头(Raspberry Pi AI Camera)教程

系列文章目录 前言 人们使用 Raspberry Pi 产品构建人工智能项目的时间几乎与我们生产 Raspberry Pi 的时间一样长。随着我们发布功能越来越强大的设备&#xff0c;我们能够支持的原生应用范围也在不断扩大&#xff1b;但无论哪一代产品&#xff0c;总会有一些工作负载需要外部…

嵌入式外设应用(代码)

文章目录 1. 工业自动化2. 智能家居设备3. 汽车电子4. 生命体征监测仪5. 物联网应用 嵌入式外设应用广泛&#xff0c;有很多应用领域&#xff1a; 1. 工业自动化 应用场景&#xff1a;使用传感器监测设备状态&#xff0c;控制电机的启动和停止。 示例代码&#xff1a; #inc…

Stream流的终结方法(二)——collect

1.Stream流的终结方法 2. collect方法 collect方法用于收集流中的数据放到集合中去&#xff0c;可以将流中的数据放到List&#xff0c;Set&#xff0c;Map集合中 2.1 将流中的数据收集到List集合中 package com.njau.d10_my_stream;import java.util.*; import java.util.f…

SSL VPN | Easyconnect下载安装使用 (详尽)

EasyConnect是一款远程连接工具&#xff0c;为用户提供简便、快捷的远程访问和控制解决方案。 目录 下载 安装 使用 卸载 下载 通过链接进入官网技术支持板块 深信服技术支持-简单、高效、自助化服务 (sangfor.com.cn)https://support.sangfor.com.cn/ 选择软件下载 在安…

ElasticSearch学习笔记(三)Ubuntu 2204 server elasticsearch集群配置

如果你只是学习elasticsearch的增、删、改、查等相关操作&#xff0c;那么在windows上安装一个ES就可以了。但是你如果想在你的生产环境中使用Elasticsearch提供的强大的功能&#xff0c;那么还是建议你使用Linux操作系统。 本文以在Ubuntu 2204 server中安装elasticsearch 8.…

Redis:hash类型

Redis&#xff1a;hash类型 hash命令设置与读取HSETHGETHMGET 哈希操作HEXISTSHDELHKEYSHVALSHGETALLHLENHSETNXHINCRBYHINCRBYFLOAT 内部编码ziplisthashtable 目前主流的编程语言中&#xff0c;几乎都提供了哈希表相关的容器&#xff0c;Redis自然也会支持对应的内容&#xf…

【Godot4.3】用2D网格模拟一点透视

概述 空间的透视是可以在二维平面上参数化计算和模拟的。本篇基于CanvasItem绘制函数draw_colored_polygon()自带的UV坐标和贴图功能&#xff0c;实现基础的平行透视效果。 或者可以叫做一点透视&#xff0c;由一个消失点决定物体的透视效果。 测试代码 extends Node2Dvar re…

【课程学习】Wireless Communications

Goldsmith A. Wireless communications[M]. Cambridge university press, 2005. Wireless Communications 无线通信课程 文章目录 2-Path Loss, Shadowing, and Multipath2.4-Two-Ray Multipath Model时延扩展 delay spread P33 3-Statistical Multipath Channel Models3.3-Wid…

HarmonyOS应用六之应用程序进阶一

目录&#xff1a; 1、UIAbility的冷启动和UIAbility热启动2、静态资源和动态资源的访问3、页面跳转3.1、页面返回跳转 4、HAR的ArkUI组件、接口、资源&#xff0c;供其他应用或当前应用的其他模块引用4.1、导出HAR的ArkUI组件4.2、引用HAR的ArkUI组件 5、循环渲染6、状态管理最…

【MySQL】多表联合查询常见练习题

数据库表如下&#xff1a; teacher&#xff1a;老师表 course&#xff1a;课程表 student&#xff1a;学生表 class&#xff1a;班级表 sc&#xff1a;成绩表 一、根据上面5张表写sql语句 1. 查询” 01 “课程比” 02 “课程成绩高的学生的信息及课程分数 select student.…