104 lines
2.4 KiB
C
104 lines
2.4 KiB
C
/* 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);
|
||
}
|
||
|