用 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。 因此,会打印一条错误消息。
相关文章
在 C++ 中获取鼠标位置
发布时间:2023/08/28 浏览次数:136 分类:C++
-
本文讲述如何在 C++ 中获取鼠标位置。在 C++ 中获取鼠标位置 C++ 提供了 GetCursorPos 方法来获取鼠标光标的 x 和 y 位置。
C++ 中的多维向量
发布时间:2023/08/28 浏览次数:150 分类:C++
-
这个简短的编程教程是关于 C++ 中多维向量的介绍。 向量是可以像 C++ 中的动态数组一样存储数据的容器,具有自动调整大小的功能。C++ 中的多维向量
在 C++ 中释放 std::vector 对象
发布时间:2023/08/28 浏览次数:52 分类:C++
-
本文将解释如何在 C++/C 中释放 std::vector 对象。 首先,我们将了解释放的自编码方式,然后,我们将研究如何在 C++ 中动态释放 std::vector 对象。在 C++ 中释放对象
在 C++ 中计算两个向量之间的角度
发布时间:2023/08/28 浏览次数:173 分类:C++
-
矢量数学是处理矢量的数学分支,矢量是具有大小和方向的几何对象。 例如,向量尾部形成的角度等于两个向量形成的角度
调整 2D 矢量大小 C++
发布时间:2023/08/28 浏览次数:138 分类:C++
-
在这篇短文中,我们将重点讨论如何在 C++ 中调整 2d 向量的大小。在 C++ 中调整 2D 矢量大小 要在 C++ 中调整二维向量的大小,我们需要使用名为 resize() 的函数
C++ 中的向量迭代器
发布时间:2023/08/28 浏览次数:163 分类:C++
-
本文介绍如何在 C++ 中迭代向量。C++ 提供了许多迭代向量的方法。 这些方法称为迭代器,它指向STL容器的内存地址;
使用 C++ 将文件读入二叉搜索树
发布时间:2023/08/27 浏览次数:52 分类:C++
-
本文将讨论将文件读入 C++ 中的二叉搜索树。 首先,我们将快速讨论二叉搜索树及其操作。稍后我们将看到如何将文件读入二叉搜索树。C++ 中的二叉搜索树
C++中逐级打印二叉树中的数据
发布时间:2023/08/27 浏览次数:183 分类:C++
-
二叉树的逐层遍历称为广度优先遍历。 本教程将教您如何使用 C++ 逐级打印二叉树中的数据,并让您熟悉执行此任务的不同方法。
用 C++ 构建解析树
发布时间:2023/08/27 浏览次数:100 分类:C++
-
本文将教授三种主要的 C++ 方法来在 C++ 中构建解析树。 第一种方法使用选择语句 if (条件) 语句和 if (条件) 语句 else 语句。