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

Linux标准IO-系统调用详解

1.1 系统调用

系统调用(system call)其实是 Linux 内核提供给应用层的应用编程接口(API),是 Linux 应用层进入内核的入口。不止 Linux 系统,所有的操作系统都会向应用层提供系统调用,应用程序通过系统调用来使用操作系统提供的各种服务。

通过系统调用,Linux 应用程序可以请求内核以自己的名义执行某些事情,譬如打开磁盘中的文件、读写文件、关闭文件以及控制其它硬件外设。

通过系统调用 API,应用层可以实现与内核的交互,其关系可通过下图简单描述:

图 1.1.1 内核、系统调用与应用程序

内核提供了一系列的服务、资源、支持一系列功能,应用程序通过调用系统调用 API 函数来使用内核提供的服务、资源以及各种各样的功能,如果大家接触过其它操作系统编程,想必对此并不陌生,譬如Windows 应用编程,操作系统内核一般都会向应用程序提供应用编程接口 API,否则我们将我无法使用操作系统。

应用编程与裸机编程、驱动编程有什么区别?

在学习应用编程之前,相信大家都有过软件开发经验,譬如 51、STM32 等单片机软件开发、以及嵌入式 Linux 硬件平台下的驱动开发等,51、STM32 这类单片机的软件开发通常是裸机程序开发,并不会涉及到操作系统的概念,那应用编程与裸机编程以及驱动开发有什么区别呢?

就拿嵌入式 Linux 硬件平台下的软件开发来说,我们大可将编程分为三种,分别为

  • 裸机编程
  • Linux 应用编程
  • Linux 驱动编程

首先对于裸机编程这个概念来说很好理解,一般把没有操作系统支持的编程环境称为裸机编程环境,譬如单片机上的编程开发,编写直接在硬件上运行的程序,没有操作系统支持;狭义上 Linux 驱动编程指的是基于内核驱动框架开发驱动程序,驱动开发工程师通过调用 Linux 内核提供的接口完成设备驱动的注册,驱动程序负责底层硬件操作相关逻辑,如果学习过 Linux 驱动开发的读者,想必对此并不陌生;而 Linux 应用编程(系统编程)则指的是基于 Linux 操作系统的应用编程,在应用程序中通过调用系统调用 API 完成应用程序的功能和逻辑,应用程序运行于操作系统之上。

通常在操作系统下有两种不同的状态:

内核态和用户态,应用程序运行在用户态、而内核则运行在内核态。

关于应用编程这个概念,以上给大家解释得很清楚了,以实现点亮一个 LED 功能为例,给大家简单地说明三者之间的区别,LED 裸机程序如下所示:

static void led_on(void) {/* 点亮 LED 硬件操作代码 */
}static void led_off(void) {/* 熄灭 LED 硬件操作代码 */
}int main(void) {/* 用户逻辑 */for ( ; ; ) {led_on(); //点亮 LEDdelay(); //延时led_off(); //熄灭 LEDdelay(); //延时} 
}

可以看到在裸机程序当中,LED 硬件操作代码与用户逻辑代码全部都是在同一个源文件(同一个工程)中实现的,硬件操作代码与用户逻辑代码没有隔离,没有操作系统支持,代码编译之后直接在硬件平台运行,俗称“裸跑”。我们再来看一个 Linux 系统下的 LED 驱动程序示例代码,如下所示:

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/delay.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>static void led_on(void) {/* 点亮 LED 硬件操作代码 */
}static void led_off(void) {/* 熄灭 LED 硬件操作代码 */
}static int led_open(struct inode *inode, struct file *filp) {/* 打开设备时需要做的事情 */
}static ssize_t led_write(struct file *filp, const char __user *buf,size_t size, loff_t *offt){int flag;/* 获取应用层 write 的数据,存放在 flag 变量 */if (copy_from_user(&flag, buf, size))return -EFAULT;/* 判断用户写入的数据,如果是 0 则熄灭 LED,如果是非 0 则点亮 LED */if (flag)led_on();elseled_off();return 0; 
}static int led_release(struct inode *inode, struct file *filp) {/* 关闭设备时需要做的事情 */
}
static struct file_operations led_fops = {.owner = THIS_MODULE,.open = led_open,.write = led_write,.release = led_release,
};static int led_probe(struct platform_device *pdev) {/* 驱动加载时需要做的事情 */
}static int led_remove(struct platform_device *pdev) {/* 驱动卸载时需要做的事情 */
}static const struct of_device_id led_of_match[] = {
{ .compatible = "alientek,led", },{ /* sentinel */ },
};MODULE_DEVICE_TABLE(of, led_of_match);
static struct platform_driver led_driver = {.driver = {.owner = THIS_MODULE,.name = "led",.of_match_table = led_of_match,},.probe = led_probe,.remove = led_remove,
};
module_platform_driver(led_driver);
MODULE_DESCRIPTION("LED Driver");
MODULE_LICENSE("GPL");

以上并不是一个完整的 LED 驱动代码,如果没有接触过 Linux 驱动开发的读者,看不懂也没有关系, 并无大碍,此驱动程序使用了最基本的字符设备驱动框架编写而成,非常简单;led_fops 对象中提供了 open、 write、release 方法,当应用程序调用 open 系统调用打开此 LED 设备时会执行到 led_open 函数,当调用 close 系统调用关闭 LED 设备时会执行到 led_release 函数,而调用 write 系统调用时会执行到 led_write 函数,此驱动程序的设定是当应用层调用 write 写入 0 时熄灭 LED,write 写入非 0 时点亮 LED。

驱动程序属于内核的一部分,当操作系统启动的时候会加载驱动程序,可以看到 LED 驱动程序中仅仅实现了点亮/熄灭 LED 硬件操作相关逻辑代码,应用程序可通过 write 这个系统调用 API 函数控制 LED 亮灭;接下来我们看看 Linux 系统下的 LED 应用程序示例代码,如下所示:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main(int argc, char **argv) {int fd;int data;fd = open("/dev/led", O_WRONLY);//打开 LED 设备(假定 LED 的设备文件为/dev/led)if (0 > fd)return -1;for ( ; ; ) {data = 1;write(fd, &data, sizeof(data)); //写 1 点亮 LEDsleep(1); //延时 1 秒data = 0;write(fd, &data, sizeof(data)); //写 0 熄灭 LEDsleep(1); //延时 1 秒}close(fd);return 0; 
}

此应用程序也非常简单,仅只需实现用户逻辑代码即可,循环点亮、熄灭 LED,并不需要实现硬件操作相关,示例代码中调用了 open、write、close 这三个系统调用 API 接口,open 和 close 分别用于打开/关闭LED 设备,write 写入数据传给 LED 驱动,传入 0 熄灭 LED,传入非 0 点亮 LED。

LED 应用程序与 LED 驱动程序是分隔、分离的,它们单独编译,它们并不是整合在一起的,应用程序运行在操作系统之上,有操作系统支持,应用程序处于用户态,而驱动程序处于内核态,与纯粹的裸机程序存在着质的区别。Linux 应用开发与驱动开发是两个不同的方向,将来在工作当中也会负责不同的任务、解决不同的问题。

相关文章:

Linux标准IO-系统调用详解

1.1 系统调用 系统调用&#xff08;system call&#xff09;其实是 Linux 内核提供给应用层的应用编程接口&#xff08;API&#xff09;&#xff0c;是 Linux 应用层进入内核的入口。不止 Linux 系统&#xff0c;所有的操作系统都会向应用层提供系统调用&#xff0c;应用程序通…...

LeetCode004-两个有序数组的中位数-最优算法代码讲解

最有帮助的视频讲解 【LeetCode004-两个有序数组的中位数-最优算法代码讲解】 https://www.bilibili.com/video/BV1H5411c7oC/?share_sourcecopy_web&vd_sourceafbacdc02063c57e7a2ef256a4db9d2a 时间复杂度 O ( l o g ( m i n ( m , n ) ) ) O(log(min(m,n))) O(log(min(…...

Unity携程Coroutine用法

一.携程概述 官方的解释是&#xff0c;携程允许你可以在多个帧中执行任务。在Unity中&#xff0c;携程是一个可以暂停并在后续帧中从暂停处继续执行的方法。 二.携程写法 下面示例使用携程和Update打印前5帧的时间间隔&#xff0c;展示了携程的基础写法 using System.Colle…...

腾讯百度阿里华为常见算法面试题TOP100(5):子串、堆

之前总结过字节跳动TOP50算法面试题: 字节跳动常见算法面试题top50整理_沉迷单车的追风少年-CSDN博客_字节算法面试题 子串 560.和为K的子数组...

「数据科学」清洗数据,真实数据集中缺失值的查看与处理

在数据科学的工作过程中&#xff0c;我们通过查看数据的基本要素和元数据之后&#xff0c;需要根据查看的结果&#xff0c;考虑是否需要清洗数据。缺失值的查看与处理&#xff0c;就是清洗数据的一部分。如果我们的数据集中&#xff0c;存在缺失值的话&#xff0c;就需要考虑如…...

彩蛋岛 销冠大模型案例

彩蛋岛 销冠大模型案例 任务&#xff1a; https://kkgithub.com/InternLM/Tutorial/tree/camp3/docs/EasterEgg/StreamerSales 视频 https://www.bilibili.com/video/BV1f1421b7Du/?vd_source4ffecd6d839338c9390829e56a43ca8d 项目git地址&#xff1a; https://kkgithu…...

大数据Flink(一百二十一):Flink CDC基本介绍

文章目录 Flink CDC基本介绍 一、什么是CDC 二、CDC的实现机制 三、​​​​​​​​​​​​​​传统 CDC ETL 分析 四、​​​​​​​​​​​​​​基于 Flink CDC 的 ETL 分析 五、​​​​​​​​​​​​​​什么是 Flink CDC 六、​​​​​​​​​​​​​​…...

SqlServer自定义类型的使用

目录 前言分类基于标量类型新建查询语句 用户定义的表类型新建查询语句 基于 CLR新建查询语句 前言 最近接触了SqlServer的自定义类型–TYPE&#xff0c;在此记录一下所得 分类 在 SQL Server 中&#xff0c;用户定义的类型&#xff08;User-Defined Types, UDT&#xff09;…...

LeetCode 滑动窗口 滑动子数组的美丽值

滑动子数组的美丽值 给你一个长度为 n 的整数数组 nums &#xff0c;请你求出每个长度为 k 的子数组的 美丽值 。 一个子数组的 美丽值 定义为&#xff1a;如果子数组中第 x 小整数 是 负数 &#xff0c;那么美丽值为第 x 小的数&#xff0c;否则美丽值为 0 。 请你返回一个包含…...

【JavaEE初阶】多线程(4)

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 线程安全的 第四个原因 代码举例: 分析原因 解决方法 方法1 方法2 wait(等待)和notify(通知) wait和sleep区别 线程安全的 第四个原因 内存可见性,引起的线程安全问…...

初识 C++ ( 1 )

引言&#xff1a;大家都说c是c的升级语言。我不懂这句话的含义后来看过解释才懂。 一、面向过程语言和面向对象语言 我们都知道C语言是面向过程语言&#xff0c;而C是面向对象语言&#xff0c;说C和C的区别&#xff0c;也就是在比较面向过程和面向对象的区别。 1.面向过程和面向…...

Python数据分析 Pandas库-初步认识

Python数据分析 Pandas库-初步认识 认识Pandas ​ pandas是一个非常实用的Python工具&#xff0c;我们可以把它想象成一个超级强大的表格处理工具&#xff0c;它比Excel更智能&#xff0c;操作更为简单。pands可以从各种文件格式&#xff08;CSV、JSON、SQL、Excel&#xff0…...

Flutter问题记录 - 适配Xcode 16和iOS 18

文章目录 前言开发环境问题及解决方案1. Upload Symbols Failed2. type UIApplication does not conform to protocol Launcher3. method does not override any method from its superclass 最后 前言 为了新的镜像功能升级了macOS 15和iOS 18&#xff0c;Xcode也不可避免的需…...

VMware ESXi 7.0U3q macOS Unlocker 集成驱动版更新 OEM BIOS 2.7 支持 Windows Server 2025

VMware ESXi 7.0U3q macOS Unlocker 集成驱动版更新 OEM BIOS 2.7 支持 Windows Server 2025 VMware ESXi 7.0U3q macOS Unlocker & OEM BIOS 2.7 集成网卡驱动和 NVMe 驱动 (集成驱动版) ESXi 7.0U3 标准版集成 Intel 网卡、Realtek USB 网卡 和 NVMe 驱动 请访问原文链…...

大数相乘,大数相加

大数相乘&#xff1a; #include <iostream> #include <vector> #include <string>std::vector<int> multiply(const std::vector<int>& num1, const std::vector<int>& num2) {int n1 num1.size();int n2 num2.size();std::ve…...

Spring Boot配置文件敏感信息加密

一&#xff0c;背景 Spring Boot应用中的数据库、Redis、Nacos、MQ等的用户名、连接地址、密码在配置文件中一般都是明文存储&#xff0c;如果系统被系统攻破或者配置文件所在的目录读权限被破解&#xff0c;又或者是动态配置文件被窃取&#xff0c;内部人员或者黑客很容易通过…...

Java操作数栈分析

Java 的操作数栈&#xff08;Operand Stack&#xff09;是 JVM 的运行时数据区域之一&#xff0c;位于每个线程的栈帧中。操作数栈用于临时存储操作的中间结果和数据&#xff08;操作数&#xff09;&#xff0c;在方法执行时&#xff0c;JVM 的字节码指令会对操作数栈进行操作。…...

C#|.net core 基础 - 值传递 vs 引用传递

不知道你在开发过程中有没有遇到过这样的困惑&#xff1a;这个变量怎么值被改&#xff1f;这个值怎么没变&#xff1f; 今天就来和大家分享可能导致这个问题的根本原因值传递 vs 引用传递。 在此之前我们先回顾两组基本概念&#xff1a; 值类型** vs 引用类型** **值类型&a…...

axure的下载,激活,汉化全过程,多图

1.前言 下载地址&#xff1a;https://pan.baidu.com/s/12xo1mJer2hmBK7QrYM5v-Q?pwd0107#list/path%2Fcsdn%E5%85%B1%E4%BA%AB%E6%96%87%E4%BB%B6 源文章&#xff1a;https://blog.csdn.net/iwanttostudyc/article/details/123773796?ops_request_misc%257B%2522request%25…...

LCR 026

题目&#xff1a;LCR 026 解法一&#xff1a;线性表 将链表中所有元素加入数组中&#xff0c;创建两个指针&#xff0c;分别指向数组的头部和尾部&#xff0c;然后向中间遍历 public void reorderList(ListNode head) {if (head null || head.next null || head.next.next …...

强化学习在并行机构人形机器人控制中的应用

1. 项目概述在机器人控制领域&#xff0c;强化学习(RL)正逐渐成为解决复杂动力学系统问题的有力工具。然而&#xff0c;当面对具有并行驱动机构的人形机器人时&#xff0c;传统RL训练方法往往面临一个关键挑战&#xff1a;大多数仿真环境无法准确模拟闭环运动链(Closed Kinemat…...

智能体所有权与版权:AI Agent Harness Engineering 创造的作品归谁所有?

1. 标题选项 《AI Agent创作版权迷局破解:从Harness工程原理到所有权划分的完整指南》 《智能体作品归谁?AI Agent Harness Engineering场景下的版权规则深度拆解》 《告别权属纠纷:一文搞懂AI Agent生成内容的所有权、版权与收益分配规则》 《Harness工程视角下的AI创作权:…...

网络配置工具类详解

CNet 网络配置工具类详解平台&#xff1a;仅支持 Linux&#xff0c;大量使用 ioctl 系统调用一、概述 CNet 是一个 纯静态方法的网络配置工具类&#xff0c;封装了 Linux 下常用的网络操作&#xff1a;功能类别涵盖内容IP 地址读取/设置本机 IP、子网掩码网关读取/添加/删除/设…...

抖音批量下载助手:一键构建你的专属视频素材库

抖音批量下载助手&#xff1a;一键构建你的专属视频素材库 【免费下载链接】douyinhelper 抖音批量下载助手 项目地址: https://gitcode.com/gh_mirrors/do/douyinhelper 还在为手动保存抖音视频而烦恼吗&#xff1f;想要批量获取心仪创作者的精彩内容却无从下手&#x…...

D2DX如何让暗黑破坏神2在4K显示器上流畅运行:5个关键技术解析

D2DX如何让暗黑破坏神2在4K显示器上流畅运行&#xff1a;5个关键技术解析 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 当…...

5分钟免费搞定HS2汉化:Honey Select 2完整中文补丁终极教程

5分钟免费搞定HS2汉化&#xff1a;Honey Select 2完整中文补丁终极教程 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch 还在为Honey Select 2的日文界面而烦恼吗…...

解锁你的音乐收藏:浏览器端音频解密完整指南

解锁你的音乐收藏&#xff1a;浏览器端音频解密完整指南 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库&#xff1a; 1. https://github.com/unlock-music/unlock-music &#xff1b;2. https://git.unlock-music.dev/um/web 项目地址: https://gitcod…...

从SIM800到BK A7670E:4G Cat.1模块硬件平替转接板设计全解析

1. 项目概述&#xff1a;从2G到4G的硬件平替升级 手头有个老项目&#xff0c;用的还是SIM800这种经典的2G模块&#xff0c;现在网络环境变了&#xff0c;2G退网是大势所趋&#xff0c;信号覆盖越来越差&#xff0c;项目得活下去&#xff0c;升级到4G成了刚需。但问题来了&#…...

从B站缓存困境到MP4自由:m4s-converter完整解决方案

从B站缓存困境到MP4自由&#xff1a;m4s-converter完整解决方案 【免费下载链接】m4s-converter 一个跨平台小工具&#xff0c;将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 当B站视频突然下架&#xff0c;那…...

终极解决方案:彻底解决UE4SS DLL劫持导致的系统级应用程序启动错误

终极解决方案&#xff1a;彻底解决UE4SS DLL劫持导致的系统级应用程序启动错误 【免费下载链接】RE-UE4SS Injectable LUA scripting system, SDK generator, live property editor and other dumping utilities for UE4/5 games 项目地址: https://gitcode.com/gh_mirrors/r…...