C Pointers
  • C Pointers
  • Linux Device Drivers
    • Basic Module
      • Hello world
      • Kthread
      • Tasklets
      • Workqueues
      • Timers
      • Linked List
      • File System
      • Netlink
        • Netlink : Unicast
        • Netlink : Multicast
      • SKB
    • Character Device Driver
    • Wireless Device Driver
  • Linux System Programming
  • Linux Network Programming
  • Linux Build Environments
  • OS Ports
  • FreeBSD Device Drivers
C Pointers
  • »
  • Linux Device Drivers »
  • Basic Module »
  • Netlink »
  • Netlink : Multicast
  • View page source
Previous Next

Netlink : Multicast

  • In this program, you are going to learn

  • How to communication between kernel and user space ?

  • How to use user space APIs ?

    • FD_ZERO

    • FD_SET

    • FD_ISSET

    • NLMSG_SPACE

  • How to use kernel space APIs ?

    • init_waitqueue_head

    • wait_event_interruptible

    • wake_up_interruptible

    • kthread_run

    • kthread_stop

    • kthread_should_stop

    • INIT_LIST_HEAD

    • list_head

    • list_for_each_entry

    • list_for_each_entry_safe

    • list_add_tail

    • list_del

    • nlmsg_new

    • nlmsg_put

    • NETLINK_CB

    • nlmsg_unicast

    • netlink_kernel_release

Topics in this section,

  • User program : nl_user.c

  • Kernel program : nl_kernel.c

  • Makefile

  • Compile and Load

  • Summary

  • To create a socket with socket(),

sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_USER);
  • bind() is used to bind a name to a socket

retval = bind(sock_fd, (struct sockaddr * )&src_addr, sizeof(src_addr));
  • nl_pid field of the sockaddr_nl can be filled with the calling process’ own pid.

struct sockaddr_nl src_addr;

src_addr.nl_pid = getpid();
  • Sending a Netlink Message In order to send a netlink message to the kernel or other user-space processes, another struct sockaddr_nl dest_addr needs to be supplied as the destination address, the same as sending a packet with sendmsg(). If the message is destined for the kernel, both nl_pid and nl_groups should be supplied with 0.

struct sockaddr_nl dest_addr;

dest_addr.nl_pid = 0;
dest_addr.nl_groups = 0;

struct msghdr msg;

msg.msg_name = (void * )&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
  • The netlink socket requires its own message header as well. This is for providing a common ground for netlink messages of all protocol types. Because the Linux kernel netlink core assumes the existence of the following header in each netlink message, an application must supply this header in each netlink message it sends:

struct nlmsghdr * nlh;
nlh = (struct nlmsghdr * )malloc(NLMSG_SPACE(256));

nlh->nlmsg_len = NLMSG_SPACE(256);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
  • A netlink message thus consists of nlmsghdr and the message payload. Once a message has been entered, it enters a buffer pointed to by the nlh pointer. We also can send the message to the struct msghdr msg:

struct iovec iov;

iov.iov_base = (void * )nlh;
iov.iov_len = nlh->nlmsg_len;

msg.msg_iov = &iov;
msg.msg_iovlen = 1;
  • After the above steps, a call to sendmsg() kicks out the netlink message:

retval = sendmsg(sock_fd, &msg, 0);
  • recvmsg used for Receiving Netlink Messages,

retval = recvmsg(sock_fd, &msg, 0);
  • select() function indicates which of the specified file descriptors is ready for reading, ready for writing, or has an error condition pending. If the specified condition is false for all of the specified file descriptors, select() blocks, up to the specified timeout interval, until the specified condition is true for at least one of the specified file descriptors or until a signal arrives that needs to be delivered.

retval = select(sock_fd + 1, &read_fds, NULL, NULL, NULL);
  • FD_ZERO initializes the file descriptor set fdset to have zero bits for all file descriptors.

FD_ZERO(&read_fds);
  • FD_SET sets the bit for the file descriptor fd in the file descriptor set fdset.

FD_SET(sock_fd, &read_fds);
  • FD_ISSET returns a non-zero value if the bit for the file descriptor fd is set in the file descriptor set pointed to by fdset, and 0 otherwise.

FD_ISSET(sock_fd, &read_fds);
  • See the full program below,

  1#include <linux/netlink.h>
  2#include <stdio.h>
  3#include <stdlib.h>
  4#include <unistd.h>
  5#include <string.h>
  6#include <sys/types.h>
  7#include <sys/socket.h>
  8#include <sys/select.h>
  9
 10#define NETLINK_USER 25
 11#define MAX_COUNT 40
 12
 13int main(void)
 14{
 15	struct sockaddr_nl src_addr, dest_addr;
 16	struct nlmsghdr *nlh;
 17	struct msghdr msg;
 18	struct iovec iov;
 19	char recv_buff[256];
 20	int sock_fd, retval, count;
 21
 22	sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_USER);
 23	if (sock_fd < 0) {
 24		perror("socket");
 25		return -1;
 26	}
 27
 28	memset(&src_addr, 0, sizeof(src_addr));
 29	src_addr.nl_family = AF_NETLINK;
 30	src_addr.nl_pid = getpid(); // User-space process PID
 31	src_addr.nl_groups = 0; // Unicast
 32
 33	retval = bind(sock_fd, (struct sockaddr *)&src_addr, sizeof(src_addr));
 34	if (retval < 0) {
 35		perror("bind");
 36		close(sock_fd);
 37		return -1;
 38	}
 39
 40	memset(&dest_addr, 0, sizeof(dest_addr));
 41	memset(&msg, 0, sizeof(msg));
 42
 43	dest_addr.nl_family = AF_NETLINK;
 44	dest_addr.nl_pid = 0; // To kernel
 45	dest_addr.nl_groups = 0;
 46
 47
 48	fd_set read_fds;
 49
 50	FD_ZERO(&read_fds);
 51	FD_SET(sock_fd, &read_fds);
 52
 53	count = 0;
 54	while (count < MAX_COUNT) {
 55		nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(256));
 56		if (!nlh) {
 57			perror("malloc");
 58			close(sock_fd);
 59			return -1;
 60		}
 61
 62		nlh->nlmsg_len = NLMSG_SPACE(256);
 63		nlh->nlmsg_pid = getpid();
 64		nlh->nlmsg_flags = 0;
 65
 66		iov.iov_base = (void *)nlh;
 67		iov.iov_len = nlh->nlmsg_len;
 68		msg.msg_name = (void *)&dest_addr;
 69		msg.msg_namelen = sizeof(dest_addr);
 70		msg.msg_iov = &iov;
 71		msg.msg_iovlen = 1;
 72
 73
 74		snprintf(NLMSG_DATA(nlh), 256, "Message from user (send) %d", count);
 75
 76		retval = sendmsg(sock_fd, &msg, 0);
 77		if (retval == -1) {
 78			perror("sendmsg");
 79			break;
 80		}
 81
 82		retval = select(sock_fd + 1, &read_fds, NULL, NULL, NULL);
 83		if (retval == -1) {
 84			perror("select");
 85			break;
 86		} else if (retval) {
 87			if (FD_ISSET(sock_fd, &read_fds)) {
 88				memset(recv_buff, 0, sizeof(recv_buff));
 89				retval = recvmsg(sock_fd, &msg, 0);
 90				if (retval == -1) {
 91					perror("recv");
 92					break;
 93				}
 94				printf("Received from kernel: %s\n", (char *) NLMSG_DATA(nlh));
 95			}
 96		}
 97		count++;
 98	}
 99
100	free(nlh);
101	close(sock_fd);
102
103	return 0;
104}
  • init_waitqueue_head are declared and initialized.

init_waitqueue_head(&wq_r);
init_waitqueue_head(&wq_s);
  • wait_event_interruptible is put to sleep (TASK_INTERRUPTIBLE) until the condition evaluates to true.

wait_event_interruptible(wq_s, wq_flag != 0);
wait_event_interruptible(wq_r, wq_flag != 0);
  • wake_up_interruptible wakes up only the processes that are in interruptible sleeps. Any process that sleeps on the wait queue using a noninterruptible function or macro will continue to sleep.

wake_up_interruptible(&wq_s);
wake_up_interruptible(&wq_r);
  • kthread_run is used to create and start a kernel thread.

thread = kthread_run(recv_netlink_msg_thread, NULL, "netlink_kthread");
send_thread = kthread_run(send_netlink_msg_thread, NULL, "netlink_send_kthread");
  • kthread_stop is used to stop and clean up a kernel thread created with kthread_run.

kthread_stop(thread);
kthread_stop(send_thread);
  • kthread_should_stop is to determine when thread should exit.

while (!kthread_should_stop())
  • INIT_LIST_HEAD is used to initialize a list_head structure.

INIT_LIST_HEAD(&mesg->list);
INIT_LIST_HEAD(&msg->list);
INIT_LIST_HEAD(&send_list);
  • list_head is used to initialize the list.

struct list_head(msg_list);
struct list_head(send_list);
  • list_for_each_entry is used to iterate over list of given type.

list_for_each_entry(new_node, &send_list, list)
list_for_each_entry(mesg, &send_list, list)
list_for_each_entry(new_node, &msg_list, list)
list_for_each_entry(msg, &msg_list, list)
  • list_for_each_entry_safe is used to iterate over list of given type safe against removal of list entry.

list_for_each_entry_safe(curr_node, next_node, &msg_list, list)
list_for_each_entry_safe(curr_node, next_node, &send_list, list)
  • list_add_tail is used to add a new entry.

list_add_tail(&mesg->list, &send_list);
list_add_tail(&msg->list, &msg_list);
  • list_del is used to delete entry from list.

list_del(&mesg->list);
list_del(&msg->list);
list_del(&curr_node->list);
list_del(&curr_node->list);
  • nlmsg_new using this create a netlink message.

skb_out = nlmsg_new(msg_size, 0);
  • nlmsg_put used to populate the message with data.

nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0);
  • nlmsg_unicast used to send the message to the user space application.

res = nlmsg_unicast(socket, skb_out, pid);
  • netlink_kernel_release used to release the netlink socket created with netlink_kernel_create.

netlink_kernel_release(socket);
  • See the full program below,

  1#include <linux/module.h>
  2#include <linux/init.h>
  3#include <linux/skbuff.h>
  4#include <linux/kthread.h>
  5#include <linux/sched.h>
  6#include <linux/delay.h>
  7#include <linux/netlink.h>
  8#include <net/netlink.h>
  9#include <net/net_namespace.h>
 10#include <linux/list.h>
 11#include <linux/slab.h>
 12
 13#define NETLINK_TESTFAMILY 25
 14#define MAX_PAYLOAD 1024
 15
 16struct message {
 17	char data[MAX_PAYLOAD];
 18	struct list_head list;
 19};
 20
 21struct list_head(msg_list);
 22struct list_head(send_list);
 23
 24wait_queue_head_t wq_r;
 25wait_queue_head_t wq_s;
 26
 27int wq_flag;
 28
 29static struct task_struct *thread;
 30static struct task_struct *send_thread;
 31struct sock *socket;
 32
 33static int send_netlink_msg_thread(void *arg)
 34{
 35	struct message *new_node;
 36
 37	while (!kthread_should_stop()) {
 38		wait_event_interruptible(wq_s, wq_flag != 0);
 39		if (wq_flag == 1) {
 40			list_for_each_entry(new_node, &send_list, list) {
 41				pr_info("kernel thread-1 : Sent message :  %s\n", new_node->data);
 42			}
 43		}
 44
 45		if (wq_flag == 2) {
 46			pr_info("Event came from exit function\n");
 47			return 0;
 48		}
 49		wq_flag = 0;
 50		msleep(5000);
 51	}
 52	return 0;
 53}
 54
 55int send_netlink_msg(int pid, char *msg, int msg_size)
 56{
 57	struct sk_buff *skb_out;
 58	struct nlmsghdr *nlh;
 59	int res;
 60	struct message *mesg;
 61	int count = 0;
 62
 63	skb_out = nlmsg_new(msg_size, 0);
 64	if (!skb_out) {
 65		pr_err("Failed to allocate new skb\n");
 66		return -1;
 67	}
 68
 69	nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0);
 70	if (nlh == NULL) {
 71		pr_err("nlmsg_put failaure\n");
 72		nlmsg_free(skb_out);
 73		return -1;
 74	}
 75
 76	NETLINK_CB(skb_out).dst_group = 0;
 77	strncpy(nlmsg_data(nlh), msg, msg_size);
 78
 79	res = nlmsg_unicast(socket, skb_out, pid);
 80	if (res < 0) {
 81		pr_err("Error while sending the netlink msg to the user\n");
 82		return res;
 83	}
 84
 85	mesg = kmalloc(sizeof(struct message), GFP_KERNEL);
 86
 87	strncpy(mesg->data, nlmsg_data(nlh), MAX_PAYLOAD);
 88
 89	INIT_LIST_HEAD(&mesg->list);
 90	list_add_tail(&mesg->list, &send_list);
 91
 92	list_for_each_entry(mesg, &send_list, list) {
 93		count++;
 94		if (count > 50) {
 95			list_del(&mesg->list);
 96			kfree(mesg);
 97		}
 98	}
 99
100	wq_flag = 2;
101	wake_up_interruptible(&wq_s);
102
103	return 0;
104}
105
106
107static int recv_netlink_msg_thread(void *arg)
108{
109	struct message *new_node;
110
111	while (!kthread_should_stop()) {
112		wait_event_interruptible(wq_r, wq_flag != 0);
113		if (wq_flag == 1) {
114			list_for_each_entry(new_node, &msg_list, list) {
115				pr_info("kernel thread-1 : Received message :  %s\n", new_node->data);
116			}
117		}
118
119		if (wq_flag == 2) {
120			pr_info("Event came from exit function\n");
121			return 0;
122		}
123		wq_flag = 0;
124		msleep(5000);
125	}
126	return 0;
127}
128
129
130static void recv_netlink_msg(struct sk_buff *skb)
131{
132	struct nlmsghdr *nlh;
133	struct message *msg;
134	int pid;
135	int count = 0;
136
137	nlh = (struct nlmsghdr *) skb->data;
138	msg = kmalloc(sizeof(struct message), GFP_KERNEL);
139	if (!msg) {
140		pr_err("Failed to allocate memory\n");
141		return;
142	}
143	pid = nlh->nlmsg_pid;
144	strscpy(msg->data, nlmsg_data(nlh), MAX_PAYLOAD);
145
146	INIT_LIST_HEAD(&msg->list);
147	list_add_tail(&msg->list, &msg_list);
148
149	list_for_each_entry(msg, &msg_list, list) {
150		count++;
151		if (count > 50) {
152			list_del(&msg->list);
153			kfree(msg);
154		}
155	}
156
157	send_netlink_msg(pid, "Hello from kernel", strlen("Hello from kernel"));
158	wq_flag = 1;
159	wake_up_interruptible(&wq_r);
160
161}
162
163
164static int __init netlink_init(void)
165{
166	struct netlink_kernel_cfg cfg = {
167		.input = recv_netlink_msg,
168	};
169
170	INIT_LIST_HEAD(&msg_list);
171	INIT_LIST_HEAD(&send_list);
172
173	socket = netlink_kernel_create(&init_net, NETLINK_TESTFAMILY, &cfg);
174	if (socket == NULL)
175		return -1;
176
177	init_waitqueue_head(&wq_r);
178	init_waitqueue_head(&wq_s);
179
180	thread = kthread_run(recv_netlink_msg_thread, NULL, "netlink_kthread");
181	if (IS_ERR(thread)) {
182		pr_alert("Error in creating kernel thread\n");
183		netlink_kernel_release(socket);
184		return PTR_ERR(thread);
185	}
186
187	send_thread = kthread_run(send_netlink_msg_thread, NULL, "netlink_send_kthread");
188	if (IS_ERR(send_thread)) {
189		pr_alert("Error in creating kernel thread\n");
190		netlink_kernel_release(socket);
191		return PTR_ERR(send_thread);
192	}
193
194	pr_info("Netlink kernel module initialized\n");
195	return 0;
196}
197
198static void __exit netlink_exit(void)
199{
200	struct message *curr_node, *next_node;
201
202	wq_flag = 2;
203	wake_up_interruptible(&wq_r);
204	wake_up_interruptible(&wq_s);
205
206	if (thread) {
207		kthread_stop(thread);
208		thread = NULL;
209	}
210
211	if (send_thread) {
212		kthread_stop(send_thread);
213		send_thread = NULL;
214	}
215
216	list_for_each_entry_safe(curr_node, next_node, &msg_list, list) {
217		list_del(&curr_node->list);
218		kfree(curr_node);
219	}
220
221	list_for_each_entry_safe(curr_node, next_node, &send_list, list) {
222		list_del(&curr_node->list);
223		kfree(curr_node);
224	}
225
226	if (socket)
227		netlink_kernel_release(socket);
228
229	pr_info("Netlink kernel module exited\n");
230}
231
232module_init(netlink_init);
233module_exit(netlink_exit);
234
235MODULE_LICENSE("GPL");
236MODULE_AUTHOR("Linux_usr");
237MODULE_DESCRIPTION("Netlink");
 1obj-m += nl_kernel.o
 2all:
 3	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
 4
 5client:
 6	gcc nl_user.c -o nl_user
 7
 8clean:
 9	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
10	rm nl_user
  1$ make all
  2
  3$ sudo insmod ./nl_kernel.ko
  4
  5$ ./nl_user
  6Received from kernel: Hello from kernel
  7Received from kernel: Hello from kernel
  8Received from kernel: Hello from kernel
  9Received from kernel: Hello from kernel
 10Received from kernel: Hello from kernel
 11Received from kernel: Hello from kernel
 12Received from kernel: Hello from kernel
 13Received from kernel: Hello from kernel
 14Received from kernel: Hello from kernel
 15Received from kernel: Hello from kernel
 16Received from kernel: Hello from kernel
 17Received from kernel: Hello from kernel
 18Received from kernel: Hello from kernel
 19Received from kernel: Hello from kernel
 20Received from kernel: Hello from kernel
 21Received from kernel: Hello from kernel
 22Received from kernel: Hello from kernel
 23Received from kernel: Hello from kernel
 24Received from kernel: Hello from kernel
 25Received from kernel: Hello from kernel
 26Received from kernel: Hello from kernel
 27Received from kernel: Hello from kernel
 28Received from kernel: Hello from kernel
 29Received from kernel: Hello from kernel
 30Received from kernel: Hello from kernel
 31Received from kernel: Hello from kernel
 32Received from kernel: Hello from kernel
 33Received from kernel: Hello from kernel
 34Received from kernel: Hello from kernel
 35Received from kernel: Hello from kernel
 36Received from kernel: Hello from kernel
 37Received from kernel: Hello from kernel
 38Received from kernel: Hello from kernel
 39Received from kernel: Hello from kernel
 40Received from kernel: Hello from kernel
 41Received from kernel: Hello from kernel
 42Received from kernel: Hello from kernel
 43Received from kernel: Hello from kernel
 44Received from kernel: Hello from kernel
 45Received from kernel: Hello from kernel
 46
 47$ sudo rmmod nl_kernel
 48
 49$ dmesg
 50[ 2066.487382] Netlink kernel module initialized
 51[ 2079.443801] kernel thread-1 : Sent message :  Hello from kernel
 52[ 2079.443900] kernel thread-1 : Received message :  Message from user (send) 0
 53[ 2079.443904] kernel thread-1 : Received message :  Message from user (send) 1
 54[ 2084.449653] kernel thread-1 : Sent message :  Hello from kernel
 55[ 2084.449656] kernel thread-1 : Received message :  Message from user (send) 0
 56[ 2084.449659] kernel thread-1 : Received message :  Message from user (send) 1
 57[ 2084.449660] kernel thread-1 : Sent message :  Hello from kernel
 58[ 2084.449662] kernel thread-1 : Sent message :  Hello from kernel
 59[ 2084.449663] kernel thread-1 : Received message :  Message from user (send) 2
 60[ 2084.449665] kernel thread-1 : Received message :  Message from user (send) 3
 61[ 2084.449667] kernel thread-1 : Sent message :  Hello from kernel
 62[ 2084.449668] kernel thread-1 : Received message :  Message from user (send) 4
 63[ 2084.449670] kernel thread-1 : Received message :  Message from user (send) 5
 64[ 2084.449672] kernel thread-1 : Sent message :  Hello from kernel
 65[ 2084.449673] kernel thread-1 : Received message :  Message from user (send) 6
 66[ 2084.449675] kernel thread-1 : Sent message :  Hello from kernel
 67[ 2084.449677] kernel thread-1 : Received message :  Message from user (send) 7
 68[ 2084.449679] kernel thread-1 : Sent message :  Hello from kernel
 69[ 2084.449681] kernel thread-1 : Received message :  Message from user (send) 8
 70[ 2084.449683] kernel thread-1 : Sent message :  Hello from kernel
 71[ 2084.449685] kernel thread-1 : Received message :  Message from user (send) 9
 72[ 2084.449686] kernel thread-1 : Sent message :  Hello from kernel
 73[ 2084.449688] kernel thread-1 : Received message :  Message from user (send) 10
 74[ 2084.449690] kernel thread-1 : Sent message :  Hello from kernel
 75[ 2084.449692] kernel thread-1 : Received message :  Message from user (send) 11
 76[ 2084.449694] kernel thread-1 : Sent message :  Hello from kernel
 77[ 2084.449696] kernel thread-1 : Received message :  Message from user (send) 12
 78[ 2084.449698] kernel thread-1 : Sent message :  Hello from kernel
 79[ 2084.449699] kernel thread-1 : Received message :  Message from user (send) 13
 80[ 2084.449701] kernel thread-1 : Sent message :  Hello from kernel
 81[ 2084.449703] kernel thread-1 : Received message :  Message from user (send) 14
 82[ 2084.449704] kernel thread-1 : Sent message :  Hello from kernel
 83[ 2084.449706] kernel thread-1 : Sent message :  Hello from kernel
 84[ 2084.449708] kernel thread-1 : Received message :  Message from user (send) 15
 85[ 2084.449710] kernel thread-1 : Sent message :  Hello from kernel
 86[ 2084.449712] kernel thread-1 : Received message :  Message from user (send) 16
 87[ 2084.449714] kernel thread-1 : Sent message :  Hello from kernel
 88[ 2084.449716] kernel thread-1 : Received message :  Message from user (send) 17
 89[ 2084.449717] kernel thread-1 : Received message :  Message from user (send) 18
 90[ 2084.449719] kernel thread-1 : Sent message :  Hello from kernel
 91[ 2084.449721] kernel thread-1 : Received message :  Message from user (send) 19
 92[ 2084.449723] kernel thread-1 : Sent message :  Hello from kernel
 93[ 2084.449725] kernel thread-1 : Received message :  Message from user (send) 20
 94[ 2084.449726] kernel thread-1 : Sent message :  Hello from kernel
 95[ 2084.449728] kernel thread-1 : Received message :  Message from user (send) 21
 96[ 2084.449730] kernel thread-1 : Sent message :  Hello from kernel
 97[ 2084.449732] kernel thread-1 : Received message :  Message from user (send) 22
 98[ 2084.449733] kernel thread-1 : Sent message :  Hello from kernel
 99[ 2084.449735] kernel thread-1 : Received message :  Message from user (send) 23
100[ 2084.449737] kernel thread-1 : Sent message :  Hello from kernel
101[ 2084.449739] kernel thread-1 : Received message :  Message from user (send) 24
102[ 2084.449741] kernel thread-1 : Sent message :  Hello from kernel
103[ 2084.449743] kernel thread-1 : Received message :  Message from user (send) 25
104[ 2084.449745] kernel thread-1 : Sent message :  Hello from kernel
105[ 2084.449746] kernel thread-1 : Received message :  Message from user (send) 26
106[ 2084.449748] kernel thread-1 : Sent message :  Hello from kernel
107[ 2084.449750] kernel thread-1 : Received message :  Message from user (send) 27
108[ 2084.449752] kernel thread-1 : Sent message :  Hello from kernel
109[ 2084.449754] kernel thread-1 : Received message :  Message from user (send) 28
110[ 2084.449756] kernel thread-1 : Sent message :  Hello from kernel
111[ 2084.449758] kernel thread-1 : Received message :  Message from user (send) 29
112[ 2084.449760] kernel thread-1 : Sent message :  Hello from kernel
113[ 2084.449762] kernel thread-1 : Received message :  Message from user (send) 30
114[ 2084.449764] kernel thread-1 : Sent message :  Hello from kernel
115[ 2084.449766] kernel thread-1 : Received message :  Message from user (send) 31
116[ 2084.449767] kernel thread-1 : Sent message :  Hello from kernel
117[ 2084.449769] kernel thread-1 : Received message :  Message from user (send) 32
118[ 2084.449771] kernel thread-1 : Sent message :  Hello from kernel
119[ 2084.449773] kernel thread-1 : Received message :  Message from user (send) 33
120[ 2084.449774] kernel thread-1 : Sent message :  Hello from kernel
121[ 2084.449776] kernel thread-1 : Received message :  Message from user (send) 34
122[ 2084.449778] kernel thread-1 : Sent message :  Hello from kernel
123[ 2084.449780] kernel thread-1 : Received message :  Message from user (send) 35
124[ 2084.449781] kernel thread-1 : Sent message :  Hello from kernel
125[ 2084.449784] kernel thread-1 : Received message :  Message from user (send) 36
126[ 2084.449786] kernel thread-1 : Sent message :  Hello from kernel
127[ 2084.449787] kernel thread-1 : Received message :  Message from user (send) 37
128[ 2084.449789] kernel thread-1 : Sent message :  Hello from kernel
129[ 2084.449791] kernel thread-1 : Received message :  Message from user (send) 38
130[ 2084.449793] kernel thread-1 : Sent message :  Hello from kernel
131[ 2084.449795] kernel thread-1 : Received message :  Message from user (send) 39
132[ 2084.449796] kernel thread-1 : Sent message :  Hello from kernel
133[ 2084.449798] kernel thread-1 : Sent message :  Hello from kernel

User Space API

Learning

socket

To create a socket

bind

To bind a name to a socket

select

To monitor the activity on a set of sockets looking for sockets ready for reading, writing, or with an exception condition pending

FD_ZERO

To initialize the file descriptor set fdset to have zero bits for all file descriptors

FD_SET

To set the bit for the file descriptor fd in the file descriptor set fdset

FD_ISSET

It returns a non-zero value if the bit for the file descriptor fd is set in the file descriptor set pointed to by fdset, and 0 otherwise

sendmsg

To send netlink message

recvmsg

To receive netlink message

Kernel Space API

Learning

init_waitqueue_head

To declare and initialize

wait_event_interruptible

It sleep until a condition gets true

wake_up_interruptible

It wakes up only the processes that are in interruptible sleeps

kthread_run

To create and start a kernel thread

kthread_stop

To stop and clean up a kernel thread created with kthread_run

kthread_should_stop

To determine when thread should exit

INIT_LIST_HEAD

To initialize a list_head structure

list_head

To initialize the list

list_for_each_entry

To iterate over list of given type

list_for_each_entry_safe

To iterate over list of given type safe against removal of list entry

list_add_tail

To add a new entry

list_del

To delete entry from list

nlmsg_new

To create a netlink message

nlmsg_put

TO populate the message

nlmsg_unicast

To send the message to the user space application

netlink_kernel_release

To release the netlink socket

See Also
  • Previous Chapters

    • Hello world

    • Kthread

    • Tasklets

    • Workqueues

    • Timers

    • Linked List

    • File System

  • Other Netlink topic

    • Netlink : Unicast

Previous Next

© Copyright 2023, c-pointers.