用 C++ 编写系统调用
本文将讨论从 C++ 编写的程序中调用写入系统的方法。 首先,我们将快速刷新系统调用,特别是 write 系统调用及其原型。
稍后,我们将讨论从 C++ 程序调用 write 系统调用。
C++ 中的系统调用
每个操作系统都通过系统调用提供一组服务。 它是计算机程序向操作系统请求服务的一种机制。
系统调用提供以下服务:
- 流程创建和管理
- 主存管理
- 文件和文件系统管理
- 设备输入/输出
- 保护
- 联网
程序所需的最频繁的服务是输入/输出。 接下来,我们将讨论 write 系统调用。
程序通过 write 系统调用请求底层操作系统在某些设备上写入。
在进行写入调用之前,了解文件描述符很重要。
文件描述符
在 Unix 和基于 Unix 的操作系统中,文件描述符是唯一标识文件或其他 IO 资源(如套接字或管道)的数字。
通常,文件描述符是一个非负整数值。 程序通过文件描述符访问文件进行IO。
库函数处理 IO 并以文件描述符作为参数。
第一步是按名称打开文件(如果文件不在程序文件夹中,则为绝对/相对路径)以访问文件以进行 IO。
如果 open 函数成功打开一个文件(即,存在同名文件并且用户具有所需的权限),它将返回一个文件描述符。
int fd = open("abc.txt", O_RDONLY | O_CREAT);
open 函数有两个参数。 第一个参数是文件名,第二个参数是读取模式(例如只读模式、只写模式等)。
后续对文件的IO操作都是通过文件描述符进行的。
C++ 中的 write 系统调用
write系统调用是操作系统内核提供的最基本的例程之一。 它将数据从主内存(缓冲区)写入文件(存储在某些硬件设备上)。
write()
系统调用将 buf 指向的内存缓冲区中最多 count 个字节写入文件描述符引用的文件。
它是一个低级函数,只能理解字节。 write 调用不能用于写入记录,例如类。
因此,更高级别的输入输出函数(如 printf()
)不可避免地要执行复杂的 I/O。
我们首先看一下用于将数据写入文件的 write 系统调用的语法。
ssize_t write(int fd, const void *buf, size_t count);
write函数的三个参数详细信息是:
- 文件描述符 fd 是从打开文件的调用中获得的。 它是一个整数值。 还可以分别为标准输入、标准输出和标准错误指定值 0、1 和 2。
- 指向内存中缓冲区 buf 的指针,数据存储在主内存中。
- count 指定要从缓冲区 buf 写入 fd 指向的文件的字节数。
类型 ssize_t 和 size_t 分别是 stddef.h 中定义的有符号和无符号整数数据类型。
返回值
write 函数返回一个带符号的值。 成功时,它返回成功写入文件的字节数,有时可能小于指定的计数。
总写入字节数小于计数的可能原因可能是输出设备内存已满,或者源写入缓冲区要写入的字符数少于计数中指定的数量。
出错时,write 系统调用返回 -1,并设置 errno 来指示遇到的错误。
在这里,我们有一个完整的程序可以使用 write 系统调用写入文件。
#include<fcntl.h>
#include<errno.h>
#include<iostream>
extern int errno;
using namespace std;
int main() {
int fd, count;
fd = open("abc.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
cout << "File descriptor = " << fd << '\n';
if (fd == -1) {
// print which type of error have in a code
printf("Error Number % d\n", errno);
// print program detail "Success or failure"
perror("Program");
}
char buff[]="This is a test program to check write system call.";
count = write(fd, buff, 50);
if (count == -1)
cout << "Error writing in file";
else
cout << "Number of bytes written to the file: " << count << '\n';
close(fd);
return 0;
}
第一个头文件 fcntl.h 有一个 write 系统调用。 第二个头文件有错误函数。
在 open 函数调用中,我们以写入模式创建一个新文件名 abc.txt。 该文件之前可能存在,但使用 O_TRUNC 时,之前的内容将被删除,并创建一个新的空文件。
代码0644表示文件权限。 接下来,if 条件检查文件是否成功打开。
如果失败,将显示错误消息。
接下来,我们使用示例文本创建了一个字符数组(用作缓冲区)。 最后,我们写入文件。
第三个参数是 50,表示要从 buff 数组写入的字符数。
计数是从 write()
API 调用返回的整数值。 如果失败,该值为-1; 因此,我们检查计数并相应地打印错误消息。
如果写入操作成功,我们将得到一个正值的 count,并且 if 条件将显示成功写入文件的总字节数。
第一个输出值 3 显示文件已成功打开。 第二行50表示50个字节全部写入成功。
接下来,我们修改了 open 语句。
fd = open("abc.txt", O_RDONLY | O_CREAT | O_TRUNC, 0644);
请注意,我们已将 O_WRONLY 替换为 O_RDONLY,结果是,输出为:
File descriptor = -1
Error Number 13
Program: Permission denied
Error writing in file
我们的打开操作失败,因为不可能通过截断内容来以读取模式打开现有文件。
由于失败,您可以看到文件描述符为-1。 另外,写入操作也不成功。
如果我们在 write 系统调用之前关闭文件,结果将是 write 系统调用操作不成功。 在这种情况下,输出应该是这样的:
File descriptor = 3
Error writing in file
这里,文件描述符不为-1,但文件已关闭; 因此,write 系统调用失败。
write系统调用返回的值为-1。 因此,会打印一条错误消息。
相关文章
Arduino 复位
发布时间:2024/03/13 浏览次数:315 分类:C++
-
可以通过使用复位按钮,Softwarereset 库和 Adafruit SleepyDog 库来复位 Arduino。
Arduino 的字符转换为整型
发布时间:2024/03/13 浏览次数:181 分类:C++
-
可以使用简单的方法 toInt()函数和 Serial.parseInt()函数将 char 转换为 int。
Arduino 串口打印多个变量
发布时间:2024/03/13 浏览次数:381 分类:C++
-
可以使用 Serial.print()和 Serial.println()函数在串口监视器上显示变量值。