1, the module parameters
Application Programming:
int main (int argc, char * the argv [])
{
}
./a.out XXX yyy ZZZ
kernel programming:
the insmod xxx.ko parameter information
desired parameters can also be passed to the kernel module which, when installed , required module parameter
module parameters implemented steps of:
1) define the global variables in the module
2)
module_param (name, type, perm) ; or
module_param_array (name, type, nump, perm);
make the variable parameter module
module_param (name, type, Perm);
name, global variable name
type, type of variable
variable type core statement of support for the module parameters int Short Long charp
Perm, access
module_param_array (name, type, nump, perm);
effect: will be declared as an array parameter module
name, the name of the array
type, the data type of the array member variable
nump, the array element number of pointers
perm, access to
the experimental procedure:
the insmod moduleparam.ko
rmmod moduleparam
the insmod moduleparam.ko STR IRQ = 100 = "Hello" FISH = 1,2,3,4,5
LS / SYS / Module1 / moduleparam / parameters / no display
CD / SYS / Module1 / moduleparam / parameters /
CAT FISH
CAT IRQ
1234> IRQ echo
11,22,33,44,55,66> FISH echo
CD /
rmmod moduleparam
use scenario module parameters:
debugging code when use
REG1 = IRQ;
insmod xxx.ko IRQ = 100
rmmod xxx.ko
insmod xxx.ko IRQ = 101;
2, the system call
to talk about the understanding of system calls?
What is the system call?
The operating system provides a set of application programmer calls a special function
the role of system calls?
Kernel security protection
to ensure the security of user space to kernel calls the function of
the system call is how to achieve
the specified user space system call number
to produce soft interrupt abnormal execution into kernel mode
execution jumps to abnormal soft interrupt vector table exception handling code
in soft interrupt exception handling code according to the system call number
to find the corresponding kernel function
and performing the function
is finished the results will backtrack to the user space
system calls: arch / arm / include / asm / unistd.h
software interrupt instruction:
ARM, SWI / svc
intel, int
exception to the scale: arch / arm / kernel / entry -armv.S
soft interrupt exception handling code: arch / arm / kernel / entry -common.S
system call table: calls.S
add a new system call
CD / Home / tarena / Driver / Kernel /
VI Arch / ARM / Kernel / sys_arm.c
the asmlinkage sys_add int (int X, Y int)
{
the printk ( "<. 1>" "Enter% S \ n-", __func__ in);
return X + Y;
}
VI Arch / ARM / the include / ASM / unistd.h // add new system calls
#define __NR_add (__NR_SYSCALL_BASE + 378)
vi Arch / ARM / kernel / calls.S // update the system call table
390 the cALL (sys_add)
the make uImage
lets developers use the new kernel board
vi test.c
Open = ( "a.txt", O_RDWR) is equivalent to
syscall (. 5, "a.txt", O_RDWR)
Read (FD, buf, len) is equivalent to
the syscall (. 3, FD, buf, len)
ARM-Linux-gnueabi cortex_a9-GCC-Test test.c -o
CP Test. ./../rootfs
./test // Notice the difference between old and new kernel
3, character device driver programming
linux is implemented using the C programming
, but kernel implementation process, extensive use of object-oriented programming ideas
Implement a character device (e.g., the LCD touch screen button mouse ...) in linux
driver, its essence is to instantiate an object of type struct cdev
struct cdev
{
// device number
the dev_t dev;
const struct the file_operations OPS *;
...
}
3.1 device number
is essentially a 32bit unsigned data of the
device number = device number of the main (high 12bit) + minor number (low 20bit)
major number, for distinguishing between different types of devices
minor number, for distinguishing the same type equipment in different individuals
ls / dev / ttySAC * -l
application and registration number of the device in two ways:
1) static
2) dynamically
3.1.1 static
view which has been occupied by major number
cat / proc / devices
has never occupied a major number pick as I used
int register_chrdev_region (dev_t from, unsigned count ,
const char * name)
action: the plurality of devices registered consecutive numbers
from, the starting device number register to
COUNT, the number to be registered
name, the name of
a return value success 0
<0 Failed
void unregister_chrdev_region (dev_t from, unsigned count )
experimental procedure:
the insmod led_drv.ko
CAT / proc / devices
rmmod led_drv.ko
CAT / proc / devices
3.1.2 dynamically
dynamically allocated by the kernel using the master device is not a number
int alloc_chrdev_region (the dev_t * dev,
unsigned baseminor, unsigned COUNT,
name char * const)
dev, outgoing parameters
Returns the dispensing device to obtain a first number
baseminor, starting minor number
count, the number of consecutive equipment numbers application
name, name
cancellation: unregister_chrdev_region
3.2 operating (driving) the collection function
driver implemented a hardware device character
actually is an example of a struct cdev object is
instantiated objects struct cdev main coding process
focused on the file_operations struct
struct the file_operations
{
owner
Open
Read
Write
the mmap
Release
unlocked_ioctl
poll
...
}
particular character of a particular hardware device, only Some of these functions can be implemented
API of about 3.3 cdev kernel provided
cdev_init void (* struct cdev cdev,
const struct the file_operations * FOPS)
{
cdev-> OPS = FOPS;
...
}
// Register the cdev a student records into the database
cdev_add (struct cdev * p, dev_t dev, unsigned count )
{
p-> dev = dev;
...
}
// cdev recorded a cancellation deleted from the database of students
void cdev_del (struct cdev * p)
experimental Procedure:
. 1) the insmod led_drv.ko
find the master device using the driving and minor No.
2) development board create the device files in
the mknod / dev / myleds C 244. 5
. 3) VI test.c
FD = Open ( "/ dev / myleds", O_RDWR);
4) arm-cortex_a9-linux- gnueabi-gcc test.c -o test
execution on 5) board the Test
cp the Test ../../rootfs
./test
summary:
everything is a file in addition to socket under linux
Module parameter passing //
#include " ../../global.h " int IRQ = 0 ; char * STR = " tarena " ; int fish [ 10 ] = { 0 }; / * save the number of fish of elements * / int num_fish = 10 ; module_param(irq, int, 0644); module_param(str, charp, 0); module_param_array(fish, int, &num_fish,0600); int __init moduleparam_init(void) { int i = 0; printk("<1>" "irq=%d\n", irq); printk("<1>" "str=%s\n", str); for(; i<num_fish; i++) { printk("<1>" "fish[%d]=%d\n", i, fish[i]); } return 0; } void __exit moduleparam_exit(void) { int i = 0; printk("<1>" "irq=%d\n", irq); printk("<1>" "str=%s\n", str); for(; i<num_fish; i++) { printk("<1>" "fish[%d]=%d\n", i, fish[i]); } } module_init(moduleparam_init); module_exit(moduleparam_exit);
// Register the device number.
#include " ../../global.h " #include <Linux / fs.h> unsigned int major = 200; unsigned int minor = 5; dev the dev_t; // device number int __init led_drv_init(void) { //dev = major<<20|minor; dev = MKDEV(major, minor); register_chrdev_region(dev, 1, "myleds"); return 0; } void __exit led_drv_exit(void) { unregister_chrdev_region(dev, 1); } module_init(led_drv_init); module_exit(led_drv_exit);
// dynamic registration device number
. 1 #include " ../../global.h " 2 #include <Linux / fs.h> . 3 . 4 unsigned int Major = 0 ; . 5 unsigned int Minor = . 5 ; . 6 the dev_t dev; // device number . 7 . 8 . 9 int the __init led_drv_init ( void ) 10 { . 11 IF (Major) // static 12 is { 13 is // dev = 20 is Major << | Minor; 14 dev = MKDEV(major, minor); 15 16 register_chrdev_region(dev, 1, "myleds"); 17 } 18 else //动态注册 19 { 20 alloc_chrdev_region(&dev, minor, 1, "myleds"); 21 printk("<1>" "major=%d minor=%d\n", 22 MAJOR(dev), MINOR(dev)); 23 } 24 return 0; 25 } 26 void __exit led_drv_exit(void) 27 { 28 unregister_chrdev_region(dev, 1); 29 } 30 module_init(led_drv_init); 31 module_exit(led_drv_exit);
#include "../../global.h" #include <linux/fs.h> #include <linux/cdev.h> unsigned int major = 0; unsigned int minor = 5; dev the dev_t; // device number / * 1 defines a struct cdev variable * / struct the cdev led_cdev; static int led_open(struct inode *inode, struct file *filp) { printk("<1>" "enter %s\n", __func__); return 0; } static int led_close(struct inode *inode, struct file *filp) { printk("<1>" "enter %s\n", __func__); return 0; } struct file_operations led_fops = { .owner = THIS_MODULE, .open = led_open, .release = led_close, }; int __init led_drv_init(void) { if(major) //静态 { //dev = major<<20|minor; dev = MKDEV(major, minor); register_chrdev_region(dev, 1, "myleds"); } the else // dynamic registration { alloc_chrdev_region(&dev, minor, 1, "myleds"); printk("<1>" "major=%d minor=%d\n", MAJOR(dev), MINOR(dev)); } / * 2 cdev initialize variables * / cdev_init ( & led_cdev, & led_fops); / * . 3 cdev register variables * / cdev_add ( & led_cdev, dev, . 1 ); return 0; } void __exit led_drv_exit(void) { / * 4 Chu销Cdev * / Cdev_del ( Ando Led_cdev); unregister_chrdev_region(dev, 1); } module_init(led_drv_init); module_exit(led_drv_exit);