📄 shm_task.c
字号:
/* shm_task.c Set up a periodic task that increments a heartbeat array in shared memory. This example demonstrates the allocation, use and freeing of shared memory. Several different data consistency algorithms can be selected; see shm_common.h and shm_common.c for the implementations. In this code we set up a function pointer depending upon which one we want. Performance measures for the number of made and missed writes are kept in shared memory, along with a heartbeat array, so that the Linux process can print them out at the end. This example also demonstates how to pass arguments to a kernel module via 'insmod variable=<value>'. This is used to specify which algorithm to use, head/tail or read/write flags.*/#include <linux/kernel.h>#include <linux/module.h>#include <linux/version.h>#include <linux/sched.h>#include <linux/errno.h> /* ENOMEM */#include <stddef.h> /* sizeof() */#include "rtai.h"#include "rtai_sched.h"#include "rtai_shm.h" /* rtai_kmalloc(), rtai_kfree() */#include "shm_core.h" /* SHM_STRUCT, SHM_KEY, SHM_HOWMANY *//* Some newer versions define RT_SCHED_LOWEST_PRIORITY instead, so we'll get that if necessary */#if ! defined(RT_LOWEST_PRIORITY)#if defined(RT_SCHED_LOWEST_PRIORITY)#define RT_LOWEST_PRIORITY RT_SCHED_LOWEST_PRIORITY#else#error RT_SCHED_LOWEST_PRIORITY not defined#endif#endif/* THIS SOFTWARE WAS PRODUCED BY EMPLOYEES OF THE U.S. GOVERNMENT AS PART OF THEIR OFFICIAL DUTIES AND IS IN THE PUBLIC DOMAIN. When linked into the Linux kernel the resulting work is GPL. You are free to use this work under other licenses if you wish.*/#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0)MODULE_LICENSE("GPL");#endifRT_TASK shm_task;static RTIME shm_period_ns = 100000;static SHM_STRUCT * shm_ptr = 0; /* pointer to shared memory *//* In shm_common.c are several different data consistency algorithms, with symbolic names declared in shm_common.h, e.g., PETERSON, TEST_AND_SET, HEAD_TAIL. Also declared is a function pointer type, MUTEX_WRITE_FUNC, for a pointer to one of these functions. We set this here so we can switch between algorithms at run time. */int WHICH_ALGO = PETERSON; /* see MODULE_PARM() below */static MUTEX_WRITE_FUNC algo_ptr = peterson_write;static int made_writes = 0;static int missed_writes = 0;static void shm_writer(int arg){ SHM_STRUCT shm_copy; int come_back; /* persistent flag, needed for some algos */ int heartbeat; /* we increment this and fill the data array */ int t; come_back = 0; heartbeat = 0; /* In this writer code, we just reference the shared memory pointer as we would any other pointer. Here we increment a heartbeat that we write into the datap[] array, update the structure's made_writes and missed_writes, then call the function pointer that does the data consistency work. */ while (1) { heartbeat++; for (t = 0; t < SHM_HOWMANY; t++) { shm_copy.data[t] = heartbeat; } shm_copy.made_writes = made_writes; shm_copy.missed_writes = missed_writes; if (0 == (*algo_ptr)(&shm_copy, shm_ptr, &come_back)) { made_writes++; } else { missed_writes++; } rt_task_wait_period(); } return;}/* Variables in a kernel module can be set by the 'insmod' program when loading the module, e.g., 'insmod mymod.o variable=1' will set 'variable' to 1. In Linux 2.2 and later, you need to call MODULE_PARM() to declare variables as settable using this method. See "Linux Device Drivers", Alessandro Rubini, p. 385 (p.42-44 in 2nd edition).*/#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0)MODULE_PARM(WHICH_ALGO, "i"); /* "i" means an integer variable */#endifint init_module(void){ int t; int retval; RTIME shm_period_count; /* Allocate shared memory by calling void * rtai_kmalloc(int key, size_t size); which takes an integer 'key' agreed to by all memory sharers, and the size of shared memory, and returns a pointer to it. */ shm_ptr = rtai_kmalloc(SHM_KEY, SHM_HOWMANY * sizeof(int)); if (0 == shm_ptr) { return -ENOMEM; /* can't get memory-- perhaps too big */ } /* initialize shared memory */ shm_ptr->head = 0; shm_ptr->reader = 0; shm_ptr->writer = 0; shm_ptr->favored = 0; shm_ptr->tas = 0; for (t = 0; t < SHM_HOWMANY; t++) { shm_ptr->data[t] = 0; } shm_ptr->made_writes = 0; shm_ptr->missed_writes = 0; shm_ptr->tail = 0; /* set up algorithm pointer */ if (WHICH_ALGO == TEST_AND_SET) { algo_ptr = test_and_set_write; } else if (WHICH_ALGO == HEAD_TAIL) { algo_ptr = head_tail_write; } /* else leave it at peterson */ /* We'll run our task as usual, a single pure periodic task */ rt_set_periodic_mode(); shm_period_count = nano2count(shm_period_ns); start_rt_timer(shm_period_count); retval = rt_task_init(&shm_task, shm_writer, 0, 1024 + sizeof(SHM_STRUCT), RT_LOWEST_PRIORITY, 0, 0); if (0 != retval) { return retval; } retval = rt_task_make_periodic(&shm_task, rt_get_time() + shm_period_count, shm_period_count); if (0 != retval) { return retval; } return 0;}void cleanup_module(void){ rt_task_delete(&shm_task); /* Free up the shared memory by calling void rtai_kfree(int key); using the same agreed-to key as we used to allocate it. */ rtai_kfree(SHM_KEY); return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -