diff --git a/index.html b/index.html
index 966c9ca..e5301e7 100644
--- a/index.html
+++ b/index.html
@@ -18,7 +18,7 @@
The Linux Kernel Module Programming Guide
Peter Jay Salzman, Michael Burian, Ori Pomerantz, Bob Mottram, Jim Huang
-July 8, 2023
+July 23, 2023
@@ -2086,25 +2086,24 @@ because data is already in kernel space.
77{
78 our_proc_file = proc_create(PROCFS_NAME, 0644, NULL, &proc_file_fops);
79 if (NULL == our_proc_file) {
-80 proc_remove(our_proc_file);
-81 pr_alert("Error:Could not initialize /proc/%s\n", PROCFS_NAME);
-82 return -ENOMEM;
-83 }
-84
-85 pr_info("/proc/%s created\n", PROCFS_NAME);
-86 return 0;
-87}
-88
-89static void __exit procfs2_exit(void)
-90{
-91 proc_remove(our_proc_file);
-92 pr_info("/proc/%s removed\n", PROCFS_NAME);
-93}
-94
-95module_init(procfs2_init);
-96module_exit(procfs2_exit);
-97
-98MODULE_LICENSE("GPL");
+80 pr_alert("Error:Could not initialize /proc/%s\n", PROCFS_NAME);
+81 return -ENOMEM;
+82 }
+83
+84 pr_info("/proc/%s created\n", PROCFS_NAME);
+85 return 0;
+86}
+87
+88static void __exit procfs2_exit(void)
+89{
+90 proc_remove(our_proc_file);
+91 pr_info("/proc/%s removed\n", PROCFS_NAME);
+92}
+93
+94module_init(procfs2_init);
+95module_exit(procfs2_exit);
+96
+97MODULE_LICENSE("GPL");
7.3 Manage /proc file with standard filesystem
@@ -2232,28 +2231,27 @@ input.
82 our_proc_file = proc_create(PROCFS_ENTRY_FILENAME, 0644, NULL,
83 &file_ops_4_our_proc_file);
84 if (our_proc_file == NULL) {
-85 remove_proc_entry(PROCFS_ENTRY_FILENAME, NULL);
-86 pr_debug("Error: Could not initialize /proc/%s\n",
-87 PROCFS_ENTRY_FILENAME);
-88 return -ENOMEM;
-89 }
-90 proc_set_size(our_proc_file, 80);
-91 proc_set_user(our_proc_file, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID);
-92
-93 pr_debug("/proc/%s created\n", PROCFS_ENTRY_FILENAME);
-94 return 0;
-95}
-96
-97static void __exit procfs3_exit(void)
-98{
-99 remove_proc_entry(PROCFS_ENTRY_FILENAME, NULL);
-100 pr_debug("/proc/%s removed\n", PROCFS_ENTRY_FILENAME);
-101}
-102
-103module_init(procfs3_init);
-104module_exit(procfs3_exit);
-105
-106MODULE_LICENSE("GPL");
+85 pr_debug("Error: Could not initialize /proc/%s\n",
+86 PROCFS_ENTRY_FILENAME);
+87 return -ENOMEM;
+88 }
+89 proc_set_size(our_proc_file, 80);
+90 proc_set_user(our_proc_file, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID);
+91
+92 pr_debug("/proc/%s created\n", PROCFS_ENTRY_FILENAME);
+93 return 0;
+94}
+95
+96static void __exit procfs3_exit(void)
+97{
+98 remove_proc_entry(PROCFS_ENTRY_FILENAME, NULL);
+99 pr_debug("/proc/%s removed\n", PROCFS_ENTRY_FILENAME);
+100}
+101
+102module_init(procfs3_init);
+103module_exit(procfs3_exit);
+104
+105MODULE_LICENSE("GPL");
Still hungry for procfs examples? Well, first of all keep in mind, there are rumors
around, claiming that procfs is on its way out, consider using sysfs instead. Consider
using this mechanism, in case you want to document something kernel related
@@ -2418,24 +2416,23 @@ the same way as in the previous example.
98
99 entry = proc_create(PROC_NAME, 0, NULL, &my_file_ops);
100 if (entry == NULL) {
-101 remove_proc_entry(PROC_NAME, NULL);
-102 pr_debug("Error: Could not initialize /proc/%s\n", PROC_NAME);
-103 return -ENOMEM;
-104 }
-105
-106 return 0;
-107}
-108
-109static void __exit procfs4_exit(void)
-110{
-111 remove_proc_entry(PROC_NAME, NULL);
-112 pr_debug("/proc/%s removed\n", PROC_NAME);
-113}
-114
-115module_init(procfs4_init);
-116module_exit(procfs4_exit);
-117
-118MODULE_LICENSE("GPL");
+101 pr_debug("Error: Could not initialize /proc/%s\n", PROC_NAME);
+102 return -ENOMEM;
+103 }
+104
+105 return 0;
+106}
+107
+108static void __exit procfs4_exit(void)
+109{
+110 remove_proc_entry(PROC_NAME, NULL);
+111 pr_debug("/proc/%s removed\n", PROC_NAME);
+112}
+113
+114module_init(procfs4_init);
+115module_exit(procfs4_exit);
+116
+117MODULE_LICENSE("GPL");
If you want more information, you can read this web page:
@@ -4048,95 +4045,94 @@ $
194 our_proc_file =
195 proc_create(PROC_ENTRY_FILENAME, 0644, NULL, &file_ops_4_our_proc_file);
196 if (our_proc_file == NULL) {
-197 remove_proc_entry(PROC_ENTRY_FILENAME, NULL);
-198 pr_debug("Error: Could not initialize /proc/%s\n", PROC_ENTRY_FILENAME);
-199 return -ENOMEM;
-200 }
-201 proc_set_size(our_proc_file, 80);
-202 proc_set_user(our_proc_file, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID);
-203
-204 pr_info("/proc/%s created\n", PROC_ENTRY_FILENAME);
-205
-206 return 0;
-207}
-208
-209/* Cleanup - unregister our file from /proc. This could get dangerous if
-210 * there are still processes waiting in waitq, because they are inside our
-211 * open function, which will get unloaded. I'll explain how to avoid removal
-212 * of a kernel module in such a case in chapter 10.
-213 */
-214static void __exit sleep_exit(void)
-215{
-216 remove_proc_entry(PROC_ENTRY_FILENAME, NULL);
-217 pr_debug("/proc/%s removed\n", PROC_ENTRY_FILENAME);
-218}
-219
-220module_init(sleep_init);
-221module_exit(sleep_exit);
-222
-223MODULE_LICENSE("GPL");
+197 pr_debug("Error: Could not initialize /proc/%s\n", PROC_ENTRY_FILENAME);
+198 return -ENOMEM;
+199 }
+200 proc_set_size(our_proc_file, 80);
+201 proc_set_user(our_proc_file, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID);
+202
+203 pr_info("/proc/%s created\n", PROC_ENTRY_FILENAME);
+204
+205 return 0;
+206}
+207
+208/* Cleanup - unregister our file from /proc. This could get dangerous if
+209 * there are still processes waiting in waitq, because they are inside our
+210 * open function, which will get unloaded. I'll explain how to avoid removal
+211 * of a kernel module in such a case in chapter 10.
+212 */
+213static void __exit sleep_exit(void)
+214{
+215 remove_proc_entry(PROC_ENTRY_FILENAME, NULL);
+216 pr_debug("/proc/%s removed\n", PROC_ENTRY_FILENAME);
+217}
+218
+219module_init(sleep_init);
+220module_exit(sleep_exit);
+221
+222MODULE_LICENSE("GPL");
-
1/*
-2 * cat_nonblock.c - open a file and display its contents, but exit rather than
-3 * wait for input.
-4 */
-5#include <errno.h> /* for errno */
-6#include <fcntl.h> /* for open */
-7#include <stdio.h> /* standard I/O */
-8#include <stdlib.h> /* for exit */
-9#include <unistd.h> /* for read */
-10
-11#define MAX_BYTES 1024 * 4
-12
-13int main(int argc, char *argv[])
-14{
-15 int fd; /* The file descriptor for the file to read */
-16 size_t bytes; /* The number of bytes read */
-17 char buffer[MAX_BYTES]; /* The buffer for the bytes */
-18
-19 /* Usage */
-20 if (argc != 2) {
-21 printf("Usage: %s <filename>\n", argv[0]);
-22 puts("Reads the content of a file, but doesn't wait for input");
-23 exit(-1);
-24 }
-25
-26 /* Open the file for reading in non blocking mode */
-27 fd = open(argv[1], O_RDONLY | O_NONBLOCK);
-28
-29 /* If open failed */
-30 if (fd == -1) {
-31 puts(errno == EAGAIN ? "Open would block" : "Open failed");
-32 exit(-1);
-33 }
-34
-35 /* Read the file and output its contents */
-36 do {
-37 /* Read characters from the file */
-38 bytes = read(fd, buffer, MAX_BYTES);
-39
-40 /* If there's an error, report it and die */
-41 if (bytes == -1) {
-42 if (errno == EAGAIN)
-43 puts("Normally I'd block, but you told me not to");
-44 else
-45 puts("Another read error");
-46 exit(-1);
-47 }
-48
-49 /* Print the characters */
-50 if (bytes > 0) {
-51 for (int i = 0; i < bytes; i++)
-52 putchar(buffer[i]);
-53 }
-54
-55 /* While there are no errors and the file isn't over */
-56 } while (bytes > 0);
-57
-58 return 0;
-59}
+ 1/*
+2 * cat_nonblock.c - open a file and display its contents, but exit rather than
+3 * wait for input.
+4 */
+5#include <errno.h> /* for errno */
+6#include <fcntl.h> /* for open */
+7#include <stdio.h> /* standard I/O */
+8#include <stdlib.h> /* for exit */
+9#include <unistd.h> /* for read */
+10
+11#define MAX_BYTES 1024 * 4
+12
+13int main(int argc, char *argv[])
+14{
+15 int fd; /* The file descriptor for the file to read */
+16 size_t bytes; /* The number of bytes read */
+17 char buffer[MAX_BYTES]; /* The buffer for the bytes */
+18
+19 /* Usage */
+20 if (argc != 2) {
+21 printf("Usage: %s <filename>\n", argv[0]);
+22 puts("Reads the content of a file, but doesn't wait for input");
+23 exit(-1);
+24 }
+25
+26 /* Open the file for reading in non blocking mode */
+27 fd = open(argv[1], O_RDONLY | O_NONBLOCK);
+28
+29 /* If open failed */
+30 if (fd == -1) {
+31 puts(errno == EAGAIN ? "Open would block" : "Open failed");
+32 exit(-1);
+33 }
+34
+35 /* Read the file and output its contents */
+36 do {
+37 /* Read characters from the file */
+38 bytes = read(fd, buffer, MAX_BYTES);
+39
+40 /* If there's an error, report it and die */
+41 if (bytes == -1) {
+42 if (errno == EAGAIN)
+43 puts("Normally I'd block, but you told me not to");
+44 else
+45 puts("Another read error");
+46 exit(-1);
+47 }
+48
+49 /* Print the characters */
+50 if (bytes > 0) {
+51 for (int i = 0; i < bytes; i++)
+52 putchar(buffer[i]);
+53 }
+54
+55 /* While there are no errors and the file isn't over */
+56 } while (bytes > 0);
+57
+58 return 0;
+59}
11.2 Completions
diff --git a/lkmpg-for-ht.html b/lkmpg-for-ht.html
index 966c9ca..e5301e7 100644
--- a/lkmpg-for-ht.html
+++ b/lkmpg-for-ht.html
@@ -18,7 +18,7 @@
The Linux Kernel Module Programming Guide
Peter Jay Salzman, Michael Burian, Ori Pomerantz, Bob Mottram, Jim Huang
-July 8, 2023
+July 23, 2023
@@ -2086,25 +2086,24 @@ because data is already in kernel space.
77{
78 our_proc_file = proc_create(PROCFS_NAME, 0644, NULL, &proc_file_fops);
79 if (NULL == our_proc_file) {
-80 proc_remove(our_proc_file);
-81 pr_alert("Error:Could not initialize /proc/%s\n", PROCFS_NAME);
-82 return -ENOMEM;
-83 }
-84
-85 pr_info("/proc/%s created\n", PROCFS_NAME);
-86 return 0;
-87}
-88
-89static void __exit procfs2_exit(void)
-90{
-91 proc_remove(our_proc_file);
-92 pr_info("/proc/%s removed\n", PROCFS_NAME);
-93}
-94
-95module_init(procfs2_init);
-96module_exit(procfs2_exit);
-97
-98MODULE_LICENSE("GPL");
+80 pr_alert("Error:Could not initialize /proc/%s\n", PROCFS_NAME);
+81 return -ENOMEM;
+82 }
+83
+84 pr_info("/proc/%s created\n", PROCFS_NAME);
+85 return 0;
+86}
+87
+88static void __exit procfs2_exit(void)
+89{
+90 proc_remove(our_proc_file);
+91 pr_info("/proc/%s removed\n", PROCFS_NAME);
+92}
+93
+94module_init(procfs2_init);
+95module_exit(procfs2_exit);
+96
+97MODULE_LICENSE("GPL");
7.3 Manage /proc file with standard filesystem
@@ -2232,28 +2231,27 @@ input.
82 our_proc_file = proc_create(PROCFS_ENTRY_FILENAME, 0644, NULL,
83 &file_ops_4_our_proc_file);
84 if (our_proc_file == NULL) {
-85 remove_proc_entry(PROCFS_ENTRY_FILENAME, NULL);
-86 pr_debug("Error: Could not initialize /proc/%s\n",
-87 PROCFS_ENTRY_FILENAME);
-88 return -ENOMEM;
-89 }
-90 proc_set_size(our_proc_file, 80);
-91 proc_set_user(our_proc_file, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID);
-92
-93 pr_debug("/proc/%s created\n", PROCFS_ENTRY_FILENAME);
-94 return 0;
-95}
-96
-97static void __exit procfs3_exit(void)
-98{
-99 remove_proc_entry(PROCFS_ENTRY_FILENAME, NULL);
-100 pr_debug("/proc/%s removed\n", PROCFS_ENTRY_FILENAME);
-101}
-102
-103module_init(procfs3_init);
-104module_exit(procfs3_exit);
-105
-106MODULE_LICENSE("GPL");
+85 pr_debug("Error: Could not initialize /proc/%s\n",
+86 PROCFS_ENTRY_FILENAME);
+87 return -ENOMEM;
+88 }
+89 proc_set_size(our_proc_file, 80);
+90 proc_set_user(our_proc_file, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID);
+91
+92 pr_debug("/proc/%s created\n", PROCFS_ENTRY_FILENAME);
+93 return 0;
+94}
+95
+96static void __exit procfs3_exit(void)
+97{
+98 remove_proc_entry(PROCFS_ENTRY_FILENAME, NULL);
+99 pr_debug("/proc/%s removed\n", PROCFS_ENTRY_FILENAME);
+100}
+101
+102module_init(procfs3_init);
+103module_exit(procfs3_exit);
+104
+105MODULE_LICENSE("GPL");
Still hungry for procfs examples? Well, first of all keep in mind, there are rumors
around, claiming that procfs is on its way out, consider using sysfs instead. Consider
using this mechanism, in case you want to document something kernel related
@@ -2418,24 +2416,23 @@ the same way as in the previous example.
98
99 entry = proc_create(PROC_NAME, 0, NULL, &my_file_ops);
100 if (entry == NULL) {
-101 remove_proc_entry(PROC_NAME, NULL);
-102 pr_debug("Error: Could not initialize /proc/%s\n", PROC_NAME);
-103 return -ENOMEM;
-104 }
-105
-106 return 0;
-107}
-108
-109static void __exit procfs4_exit(void)
-110{
-111 remove_proc_entry(PROC_NAME, NULL);
-112 pr_debug("/proc/%s removed\n", PROC_NAME);
-113}
-114
-115module_init(procfs4_init);
-116module_exit(procfs4_exit);
-117
-118MODULE_LICENSE("GPL");
+101 pr_debug("Error: Could not initialize /proc/%s\n", PROC_NAME);
+102 return -ENOMEM;
+103 }
+104
+105 return 0;
+106}
+107
+108static void __exit procfs4_exit(void)
+109{
+110 remove_proc_entry(PROC_NAME, NULL);
+111 pr_debug("/proc/%s removed\n", PROC_NAME);
+112}
+113
+114module_init(procfs4_init);
+115module_exit(procfs4_exit);
+116
+117MODULE_LICENSE("GPL");
If you want more information, you can read this web page:
@@ -4048,95 +4045,94 @@ $
194 our_proc_file =
195 proc_create(PROC_ENTRY_FILENAME, 0644, NULL, &file_ops_4_our_proc_file);
196 if (our_proc_file == NULL) {
-197 remove_proc_entry(PROC_ENTRY_FILENAME, NULL);
-198 pr_debug("Error: Could not initialize /proc/%s\n", PROC_ENTRY_FILENAME);
-199 return -ENOMEM;
-200 }
-201 proc_set_size(our_proc_file, 80);
-202 proc_set_user(our_proc_file, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID);
-203
-204 pr_info("/proc/%s created\n", PROC_ENTRY_FILENAME);
-205
-206 return 0;
-207}
-208
-209/* Cleanup - unregister our file from /proc. This could get dangerous if
-210 * there are still processes waiting in waitq, because they are inside our
-211 * open function, which will get unloaded. I'll explain how to avoid removal
-212 * of a kernel module in such a case in chapter 10.
-213 */
-214static void __exit sleep_exit(void)
-215{
-216 remove_proc_entry(PROC_ENTRY_FILENAME, NULL);
-217 pr_debug("/proc/%s removed\n", PROC_ENTRY_FILENAME);
-218}
-219
-220module_init(sleep_init);
-221module_exit(sleep_exit);
-222
-223MODULE_LICENSE("GPL");
+197 pr_debug("Error: Could not initialize /proc/%s\n", PROC_ENTRY_FILENAME);
+198 return -ENOMEM;
+199 }
+200 proc_set_size(our_proc_file, 80);
+201 proc_set_user(our_proc_file, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID);
+202
+203 pr_info("/proc/%s created\n", PROC_ENTRY_FILENAME);
+204
+205 return 0;
+206}
+207
+208/* Cleanup - unregister our file from /proc. This could get dangerous if
+209 * there are still processes waiting in waitq, because they are inside our
+210 * open function, which will get unloaded. I'll explain how to avoid removal
+211 * of a kernel module in such a case in chapter 10.
+212 */
+213static void __exit sleep_exit(void)
+214{
+215 remove_proc_entry(PROC_ENTRY_FILENAME, NULL);
+216 pr_debug("/proc/%s removed\n", PROC_ENTRY_FILENAME);
+217}
+218
+219module_init(sleep_init);
+220module_exit(sleep_exit);
+221
+222MODULE_LICENSE("GPL");
-
1/*
-2 * cat_nonblock.c - open a file and display its contents, but exit rather than
-3 * wait for input.
-4 */
-5#include <errno.h> /* for errno */
-6#include <fcntl.h> /* for open */
-7#include <stdio.h> /* standard I/O */
-8#include <stdlib.h> /* for exit */
-9#include <unistd.h> /* for read */
-10
-11#define MAX_BYTES 1024 * 4
-12
-13int main(int argc, char *argv[])
-14{
-15 int fd; /* The file descriptor for the file to read */
-16 size_t bytes; /* The number of bytes read */
-17 char buffer[MAX_BYTES]; /* The buffer for the bytes */
-18
-19 /* Usage */
-20 if (argc != 2) {
-21 printf("Usage: %s <filename>\n", argv[0]);
-22 puts("Reads the content of a file, but doesn't wait for input");
-23 exit(-1);
-24 }
-25
-26 /* Open the file for reading in non blocking mode */
-27 fd = open(argv[1], O_RDONLY | O_NONBLOCK);
-28
-29 /* If open failed */
-30 if (fd == -1) {
-31 puts(errno == EAGAIN ? "Open would block" : "Open failed");
-32 exit(-1);
-33 }
-34
-35 /* Read the file and output its contents */
-36 do {
-37 /* Read characters from the file */
-38 bytes = read(fd, buffer, MAX_BYTES);
-39
-40 /* If there's an error, report it and die */
-41 if (bytes == -1) {
-42 if (errno == EAGAIN)
-43 puts("Normally I'd block, but you told me not to");
-44 else
-45 puts("Another read error");
-46 exit(-1);
-47 }
-48
-49 /* Print the characters */
-50 if (bytes > 0) {
-51 for (int i = 0; i < bytes; i++)
-52 putchar(buffer[i]);
-53 }
-54
-55 /* While there are no errors and the file isn't over */
-56 } while (bytes > 0);
-57
-58 return 0;
-59}
+ 1/*
+2 * cat_nonblock.c - open a file and display its contents, but exit rather than
+3 * wait for input.
+4 */
+5#include <errno.h> /* for errno */
+6#include <fcntl.h> /* for open */
+7#include <stdio.h> /* standard I/O */
+8#include <stdlib.h> /* for exit */
+9#include <unistd.h> /* for read */
+10
+11#define MAX_BYTES 1024 * 4
+12
+13int main(int argc, char *argv[])
+14{
+15 int fd; /* The file descriptor for the file to read */
+16 size_t bytes; /* The number of bytes read */
+17 char buffer[MAX_BYTES]; /* The buffer for the bytes */
+18
+19 /* Usage */
+20 if (argc != 2) {
+21 printf("Usage: %s <filename>\n", argv[0]);
+22 puts("Reads the content of a file, but doesn't wait for input");
+23 exit(-1);
+24 }
+25
+26 /* Open the file for reading in non blocking mode */
+27 fd = open(argv[1], O_RDONLY | O_NONBLOCK);
+28
+29 /* If open failed */
+30 if (fd == -1) {
+31 puts(errno == EAGAIN ? "Open would block" : "Open failed");
+32 exit(-1);
+33 }
+34
+35 /* Read the file and output its contents */
+36 do {
+37 /* Read characters from the file */
+38 bytes = read(fd, buffer, MAX_BYTES);
+39
+40 /* If there's an error, report it and die */
+41 if (bytes == -1) {
+42 if (errno == EAGAIN)
+43 puts("Normally I'd block, but you told me not to");
+44 else
+45 puts("Another read error");
+46 exit(-1);
+47 }
+48
+49 /* Print the characters */
+50 if (bytes > 0) {
+51 for (int i = 0; i < bytes; i++)
+52 putchar(buffer[i]);
+53 }
+54
+55 /* While there are no errors and the file isn't over */
+56 } while (bytes > 0);
+57
+58 return 0;
+59}
11.2 Completions