nhmk/示例/3-ioctl/userspace_ioctl.c

104 lines
2.4 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* userspace_ioctl.c - 用于通过 ioctl 控制内核模块的进程
*
* 之前我们可以使用 cat 进行输入和输出,但现在需要使用 ioctl这要求我们编写自己的进程。
*/
/* 包含设备特定的信息,如 ioctl 编号和主设备号。 */
#include "./chardev.h"
#include <stdio.h> /* 标准输入/输出 */
#include <fcntl.h> /* 打开文件 */
#include <unistd.h> /* 关闭文件 */
#include <stdlib.h> /* 退出程序 */
#include <sys/ioctl.h> /* ioctl 调用 */
/* ioctl 调用的函数 */
int ioctl_set_msg(int file_desc, char *message)
{
int ret_val;
ret_val = ioctl(file_desc, IOCTL_SET_MSG, message);
if (ret_val < 0) {
printf("ioctl_set_msg 失败: %d\n", ret_val);
}
return ret_val;
}
int ioctl_get_msg(int file_desc)
{
int ret_val;
char message[100] = { 0 };
/* 警告 - 这里存在风险,因为我们没有告知内核写入的缓冲区长度,可能会导致缓冲区溢出。在实际生产程序中,
* 我们应该使用两个 ioctl 调用 - 一个告知内核缓冲区长度,另一个提供要填充的缓冲区。
*/
ret_val = ioctl(file_desc, IOCTL_GET_MSG, message);
if (ret_val < 0) {
printf("ioctl_get_msg 失败: %d\n", ret_val);
}
printf("获取的消息: %s", message);
return ret_val;
}
/* 注意:这种按字节读取消息的方式无法正常读取中文 */
int ioctl_get_nth_byte(int file_desc)
{
int i, c, err;
printf("按字节获取到的消息: ");
err = 0;
i = 0;
do {
c = ioctl(file_desc, IOCTL_GET_NTH_BYTE, i++);
if (c < 0) {
err = 1;
continue;
}
putchar(c);
} while (c != 0);
if (err == 1){
printf("(非ascii字符已被省略)\n\n");
}
return 0;
}
/* 主函数 - 调用 ioctl 函数 */
int main(void)
{
int file_desc, ret_val;
char *msg = "通过 ioctl 传递的消息\n";
/* char *msg = "qwer1234\n"; */
file_desc = open(DEVICE_PATH, O_RDWR);
if (file_desc < 0) {
printf("无法打开设备文件: %s, 错误: %d\n", DEVICE_PATH, file_desc);
exit(EXIT_FAILURE);
}
ret_val = ioctl_set_msg(file_desc, msg);
if (ret_val)
goto error;
ret_val = ioctl_get_nth_byte(file_desc);
if (ret_val)
goto error;
ret_val = ioctl_get_msg(file_desc);
if (ret_val)
goto error;
close(file_desc);
return 0;
error:
close(file_desc);
exit(EXIT_FAILURE);
}