ioctl: move doc to README

This commit is contained in:
Ciro Santilli
2018-07-01 17:44:38 +01:00
parent 084e3faf5a
commit d840b0cb65
7 changed files with 107 additions and 51 deletions

View File

@@ -19,7 +19,6 @@
... link:dep.c[]
... link:dep2.c[]
. Pseudo filesystems
.. link:ioctl.c[]
.. link:mmap.c[]
.. link:poll.c[]
. Asynchronous

View File

@@ -1,23 +1,4 @@
/*
Input: an integer (with some annoying restrictions) and a pointer
Output:
- positive integer return value, which for sanity should only be used with negative values for success
- the input pointer data may be overwritten to contain output
Feels like an archaic API... so many weird restrictions and types for something that could be so simple!
Documentation/ioctl/ioctl-number.txt has some info:
_IO an ioctl with no parameters
_IOW an ioctl with write parameters (copy_from_user)
_IOR an ioctl with read parameters (copy_to_user)
_IOWR an ioctl with both write and read parameters.
- https://stackoverflow.com/questions/2264384/how-do-i-use-ioctl-to-manipulate-my-kernel-module/44613896#44613896
- https://askubuntu.com/questions/54239/problem-with-ioctl-in-a-simple-kernel-module/926675#926675
*/
/* https://github.com/cirosantilli/linux-kernel-module-cheat#ioctl */
#include <linux/debugfs.h>
#include <linux/module.h>

View File

@@ -9,11 +9,10 @@ typedef struct {
int j;
} lkmc_ioctl_struct;
/* Some random number I can't understand how to choose. */
/* TODO some random number I can't understand how to choose. */
#define LKMC_IOCTL_MAGIC 0x33
/*
* I think those number does not *need* to be unique across, that is just to help debugging:
/* I think those number do not *need* to be unique across, that is just to help debugging:
* https://stackoverflow.com/questions/22496123/what-is-the-meaning-of-this-macro-iormy-macig-0-int
*
* However, the ioctl syscall highjacks several low values at do_vfs_ioctl, e.g.
@@ -25,8 +24,19 @@ typedef struct {
* https://stackoverflow.com/questions/6125068/what-does-the-fd-cloexec-fcntl-flag-do
*
* TODO are the W or R of _IOx and type functional, or only to help with uniqueness?
* */
*
* Documentation/ioctl/ioctl-number.txt documents:
*
* ....
* _IO an ioctl with no parameters
* _IOW an ioctl with write parameters (copy_from_user)
* _IOR an ioctl with read parameters (copy_to_user)
* _IOWR an ioctl with both write and read parameters.
* ....
*/
/* Take an int, increment it. */
#define LKMC_IOCTL_INC _IOWR(LKMC_IOCTL_MAGIC, 0, int)
/* Take a struct with two ints, increment the first, and decrement the second. */
#define LKMC_IOCTL_INC_DEC _IOWR(LKMC_IOCTL_MAGIC, 1, lkmc_ioctl_struct)
#endif

View File

@@ -1,3 +1,5 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#ioctl */
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
@@ -12,43 +14,53 @@
int main(int argc, char **argv)
{
int fd, arg_int, ret;
char *ioctl_path;
int fd, request, arg0, arg1, arg_int, ret;
lkmc_ioctl_struct arg_struct;
if (argc < 2) {
puts("Usage: ./prog <ioctl-file>");
puts("Usage: ./prog <ioctl-file> <request> [<arg>...]");
return EXIT_FAILURE;
}
fd = open(argv[1], O_RDONLY);
ioctl_path = argv[1];
request = strtol(argv[2], NULL, 10);
if (argc > 3) {
arg0 = strtol(argv[3], NULL, 10);
}
if (argc > 4) {
arg1 = strtol(argv[4], NULL, 10);
}
fd = open(ioctl_path, O_RDONLY);
if (fd == -1) {
perror("open");
return EXIT_FAILURE;
}
/* 0 */
switch (request)
{
arg_int = 1;
ret = ioctl(fd, LKMC_IOCTL_INC, &arg_int);
if (ret == -1) {
perror("ioctl");
case 0:
arg_int = arg0;
ret = ioctl(fd, LKMC_IOCTL_INC, &arg_int);
if (ret != -1) {
printf("%d\n", arg_int);
}
break;
case 1:
arg_struct.i = arg0;
arg_struct.j = arg1;
ret = ioctl(fd, LKMC_IOCTL_INC_DEC, &arg_struct);
if (ret != -1) {
printf("%d %d\n", arg_struct.i, arg_struct.j);
}
break;
default:
puts("error: unknown request");
return EXIT_FAILURE;
}
printf("arg = %d\n", arg_int);
printf("ret = %d\n", ret);
printf("errno = %d\n", errno);
}
puts("");
/* 1 */
{
arg_struct.i = 1;
arg_struct.j = 1;
ret = ioctl(fd, LKMC_IOCTL_INC_DEC, &arg_struct);
if (ret == -1) {
perror("ioctl");
return EXIT_FAILURE;
}
printf("arg = %d %d\n", arg_struct.i, arg_struct.j);
printf("ret = %d\n", ret);
if (ret == -1) {
perror("ioctl");
printf("errno = %d\n", errno);
return EXIT_FAILURE;
}
close(fd);
return EXIT_SUCCESS;