当前位置: 首页 > news >正文

嵌入式学习笔记--LINUX系统编程阶段--DAY02系统编程

系统编程

  • 系统编程:在有操作系统的前提下进行编程,并且借助操作系统的系统调用以及各种库,对系统资源进行访问。学会了C语言之后,再知道一些系统调用的方法,就可以进行系统编程。
  • 操作系统:用来管理所有硬件资源,并且将不同的设备进行关联的系统。

系统调用

类UNIX系统的软件层次

系统调用(syste call)是操作系统提供给用户的一层特殊的函数接口。

Linux的不同版本提供了两三百个系统调用。

用户程序可以通过这组接口获得操作系统内核提供的服务。

例如:

用户可以通过文件系统相关的系统调用,打开相应的文件,进行相关的操作。

系统调用按照逻辑功能大致可以分为:进程管理、进程间通信、内存管理、文件管理、设备控制、网络管理等。

系统调用的返回值:通常,系统调用通常用负的返回值来表示错误,用0来表示正确。用户可以用perror来打印错误信息。

系统调用遵循的规范:在Linux中,应用程序编程接口(API)遵循POSIX标准。

POSIX标准基于当时现有的UNIX 实践和经验,描述了操作系统的系统调用编程接口(实际上就是API),用于保证应用程序可以在源代码一级上在多种操作系统上移植运行。

例如:Linux下的write  read 可以直接移植到unix中

用户态和内核态

用户态:通常情况下不允许访问内核数据,也无法使用内核函数,它们只能在用户空间操作用户数据,调用用户空间函数。

内核态:内核态是系统调用函数通过系统对应预留接口,利用内核对系统资源的管理和提供。

运行在内核态的进程可以毫无限制的访问各种资源,而在用户态下的用户进程的各种操作都有着限制,比如不能随意的访问内存、不能开闭中断以及切换运行的特权级别。

 我是这么理解的:内核态就像是一个银行的金库,这个银行的金库不是谁都有权限访问,只有相应的管理员才行(操作系统内核),而其他用户就相当于用户态,用户可以存钱取钱,但是银行不可能直接把你扔进去进行存钱取钱,需要借助中间人(操作系统内核)。来进行存取操作。

系统调用与库函数的区别

如图,部分库函数是可以调用系统调用的,但是不是所有的系统调用都被封成了库函数。

库函数由两类函数组成:
1 不需要调用系统调用,不需要切换到内核空间即可完成函数全部功能,并且将结果反馈给应用程序,如strcpy 等字符串操作函数。
2 需要调用系统调用,需要切换到内核空间,这类函数通过封装系统调用去实现相应功能,如 printf、fread 等

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

系统调用I/O函数

      在 Linux 的世界里,一切设备皆文件。我们可以系统调用中 I/O 的函数(I:
input,输入;O:output,输出),对文件进行相应的操作( open()、close()、
write() 、read() 等)。

1.文件描述符

        打开现存文件或新建文件时,系统(内核)会返回一个文件描述符,文件描述符用来指定已打开的文件。这个文件描述符相当于这个已打开文件的标号,文件描述符是非负整数,是文件的标识,操作这个文件描述符相当于操作这个文件描述符所指定的文件。

        进程(程序)运行起来的时候,会产生一张文件运行表,记录当前程序打开的所有文件描述符。

        每个进程会默认打开3个文件描述符。

0   标准输入设备;(scanf)

1   标准输出设备;(printf)

2   标准错误设备;(perror)

新打开的文件描述符,为最小可用文件描述符。

一个进程最多可以打开1024个文件,即描述符从0~1023

2.open函数

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);  //打开不存在的文件,要给磁盘权限

函数解释:

  • 返回值:
    • 成功时,得到最小的可用的文件描述符
    • 失败时返回-1,可以利用perror查看信息
  • pathname:文件路径以及文件名
  • flags:open函数的行为标志(打开的模式,读或者写)
  • mode:文件权限(磁盘权限)

flag值

mode值

3.close函数

作用:关闭文件描述符

#include <unistd.h>
/*
功能:关闭已打开的文件
参数:fd : 文件描述符,open()的返回值
返回值:成功:0;失败: -1, 并设置 errno*/
int close(int fd);



4.write函数

作用:把指定内存的指定数目的数据写到文件中

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

参数:

fd:文件描述符

buf:内存首地址

count:写入数据的字节个数

返回值:

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

失败:返回-1,可以用perror查看信息

5.read函数

把指定的数目的数据读到内存中

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

参数:

fd:文件描述符

buf:内存首地址

count:读取数据的字节个数

返回值:

成功:返回读取成功的字节个数

失败:返回-1,可以用perror查看信息

6.remove函数

删除文件

 #include <stdio.h>
int remove(const char *pathname);

参数:

pathname:文件名和文件路径

返回值:

成功返回0;

失败返回-1,可以用perror查看信息

练习:使用系统调用函数实现cp指令

源文件 ./a.txt  读

目的文件:./test下的a.txt  写

代码编写后的 可执行文件  a.out

先了解外部传参:

运行结果

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include<string.h>
#include <fcntl.h>int main(int argc, char const *argv[])
{if (argc != 3){printf("./a.out  ./a.txt  ./test");}int fd_r = open(argv[1],O_RDONLY);if (fd_r < 0){perror("open");return 0;}printf("%d\n",fd_r);char dest_name[64] = "";strcpy(dest_name,argv[2]);strcat(dest_name,"/");strcat(dest_name,argv[1]);  //將路徑拼接好,放入dest_name中printf("%s\n",dest_name); int  fd_w = open(dest_name,O_WRONLY|O_CREAT,0666);while (1){char buff[128] = "";int len = read(fd_r,buff,sizeof(buff));  write(fd_w,buff,len);printf("%d\n",len);printf("%lu\n",sizeof(buff));if (len < sizeof(buff)){break;}}close(fd_r);close(fd_w);return 0;
}

http://www.dtcms.com/a/356033.html

相关文章:

  • 嵌入式学习日志————实验:串口发送串口发送+接收
  • 亚远景-ISO/PAS 8800:如何通过认证提升企业技术管理能力?
  • 入职体检空腹血糖 6.15mmol/L合格吗?
  • amis上传组件导入文件接口参数为base64格式的使用示例
  • NumPy 2.x 完全指南【三十一】布尔数组索引
  • ConcurrentHashMap的原理
  • 实战笔记——构建智能Agent:SpreadJS代码助手
  • vue3使用reactive和ref
  • 【python】python进阶——生成器
  • JDK的ConcurrentHashMap为什么放弃了分段锁
  • 大模型开发之:LangChain4j【附资料】
  • C++基础知识:虚函数和纯虚函数
  • 基于MATLAB的FIR滤波器设计与信号分离实现
  • 线性回归的法方程:原理与解析
  • 复习笔记11
  • 【K8s】整体认识K8s之pod
  • 【Git】Git 常用指令
  • 使用华为 USG6000防火墙配置安全策略
  • 今日行情明日机会——20250828
  • 驾驭巨量数据:HTTP 协议与大文件传输的多种策略
  • 【Python开源环境】Anaconda/Miniconda
  • 印度尼西亚数据源 PHP 对接文档
  • 从零搭建安全帽检测(8)— 泛化性检验:构建独立测试集与模型性能公正评估
  • 动态加载和异步调用tasklet/workqueue day63 ay64
  • 卷积神经网络搭建及应用
  • 对象之间属性拷贝(Bean Mapping)的工具MapStruct 和 BeanUtils
  • 多据点协作下的数据库权限与版本管理实战
  • BeforeEach与AfterEach注解的使用
  • React学习教程,从入门到精通, ReactJS - 安装:初学者指南(3)
  • iPhone17新品曝光!未来已来主题发布会即将登场