2.4 Common System Support
2.4.1 memory application and release
Include/Linux/kernel. h declares kmalloc () and kfree (). It is used to apply for and release memory in kernel mode.
Void * kmalloc (unsigned int Len, int priority );
Void kfree (void * _ PTR );
Unlike malloc () in user mode, the size of the kmalloc () application space is limited. The length is the integer power of 2. The maximum length that can be applied is limited. In addition, kmalloc () has the priority parameter, which can usually be gfp_kernel in use. If the gfp_atomic parameter is called in the interrupt, the caller may enter the sleep state because gfp_kernel is used, it is not allowed to handle interruptions.
The memory released by kfree () must be applied by kmalloc. If you know the memory size, you can also use kfree_s () to release it.
2.4.2 request_irq (), free_irq ()
This is the call for the driver to request and release the interrupt. Declare it in include/Linux/sched. h. Request_irq () call definition:
Int request_irq (unsigned int IRQ,
Void (* Handler) (int irq, void * dev_id, struct pt_regs * regs ),
Unsigned long irqflags,
Const char * devname,
Void * dev_id );
IRQ is the hardware interrupt number to be applied. On Intel Platform, the range is 0--15. Handler is the interrupt handler function registered with the system. This is a callback function. When an interrupt occurs, the system calls this function. The input parameters include the hardware interrupt number, device ID, and register value. Dev_id is the dev_id parameter passed to the system when request_irq is as follows. Irqflags is an attribute of Interrupt Processing. Sa_interrupt indicates whether the interrupt processing program is a fast processing program (set sa_interrupt) or a slow processing program (do not set sa_interrupt ). All interrupts are blocked when the quick processing program is called. The slow processing program is not blocked. There is also a sa_shirq attribute, which sets the sharing interruption for multiple devices to run in the future. Dev_id is used to interrupt sharing. It is generally set to the device structure of the device itself or null. The interrupt handler can use dev_id to find the device that controls the interrupt, or use rq2dev_map to find the device.
Void free_irq (unsigned int IRQ, void * dev_id );
2.4.3 clock
The clock processing is similar to the interrupt. It is also a time processing function. After the scheduled time, the system clock processing is similar to the interrupt. It is also a time processing function. After the scheduled time, the system will call this function. Declare it in include/Linux/Timer. h.
Struct timer_list {
Struct timer_list * next;
Struct timer_list * Prev;
Unsigned long expires;
Unsigned long data;
Void (* function) (unsigned long );
};
Void add_timer (struct timer_list * timer );
Int del_timer (struct timer_list * timer );
Void init_timer (struct timer_list * timer );
Use the clock to declare a timer_list structure and call init_timer to initialize it. In the time_list structure, expires indicates the cycle of the clock. The unit is jiffies. Jiffies is a global variable in Linux, representing the time. Its unit varies with the hardware platform. A constant Hz is defined in the system, representing the number of minimum time intervals per second. In this way, the unit of jiffies is 1/Hz. Jiffies of Intel Platform is measured in 1/100 seconds, which is the minimum time interval that the system can distinguish. Therefore, expires/Hz is the cycle of the clock in seconds.
Function is the callback function after the time is reached. Its parameter is data in timer_list. The data parameter is assigned a value when the clock is initialized and is generally assigned to the device structure pointer of the device.
During the preset time, the system calls the function and clears the time_list from the scheduled queue. So if you need to keep using the timer function, you need to call add_timer () again in the function to call this function.
I/O port access and usage:
Inline unsigned int INB (unsigned short port );
Inline unsigned int inb_p (unsigned short port );
Inline void outb (char value, unsigned short port );
Inline void outb_p (char value, unsigned short port );
Defined in include/ADM/IO. h.
Inb_p (), outb_p (), INB (), and outb_p () are different in that the former has a waiting time when accessing I/O.
(Pause) a slow I/O device.
To prevent access to I/O conflicts, Linux provides control over port usage. Before using the port, you can check whether the required I/O is in use. If not, mark the port as in use and release it after use. The system provides the following functions to do this.
Int check_region (unsigned int from, unsigned int extent );
Void request_region (unsigned int from, unsigned int extent, const char * name)
;
Void release_region (unsigned int from, unsigned int extent );
The from parameter indicates the starting address of the I/O port used, and the extent indicates the number of ports starting from. Name indicates the device name.
Void release_region (unsigned int from, unsigned int extent );
The from parameter indicates the starting address of the I/O port used, and the extent indicates the number of ports starting from. Name indicates the device name.
2.4.5 enable or disable an interrupt
The system provides the driver with the ability to open and close the response to interruptions. Is two definitions in include/ASM/system. h.
# Define CLI () _ ASM _ volatile _ ("CLI "::)
# Define STI () _ ASM _ volatile _ ("Sti "::)
2.4.6 print information
Similar to printf () in a common program, the driver needs to output information using printk (). Declare it in include/Linux/kernel. h.
Int printk (const char * FMT ,...);
FMT is a formatted string .... Yes. Both are in the same format as printf.
2.4.7 register the driver
If you use the module method to load the driver, you must register the device during module initialization.
Go to the system device table. Remove the device from the system when it is no longer in use. Define two functions in drivers/NET/net_init.h to complete this job.
Int register_netdev (struct device * Dev );
Void unregister_netdev (struct device * Dev );
Dev is the device structure pointer to be registered into the system. In register_netdev (), Dev is the device structure pointer to be registered into the system. During register_netdev (), the dev structure is generally filled in with the first 11 items, that is, init. Initialization is not required for the later part. The most important thing is the name pointer and init method. If the name pointer is null or the content is or name [0] is space, the system processes your device as an Ethernet device. Ethernet devices have a uniform naming format, ethx. The special treatment of Ethernet is probably related to the history of Linux.
The init method must be provided. register_netdev () will call this method to check and set the hardware.
Register_netdev () returns 0, indicating that the operation is successful. Otherwise, the operation fails.
2.4.8 sk_buff
Data transmission between different layers of the Linux network is through sk_buff. Sk_buff provides a set of buffer management methods, which is the key to the efficient operation of the Linux system network. Each sk_buff includes some control methods and a data buffer. The control method is divided into two types by function. One method is to control the entire buffer chain, and the other is to control the data buffer. Sk_buff is organized into a two-way linked list. According to the characteristics of network applications, the operation on the linked list is mainly to delete the elements of the linked list header and add them to the end of the linked list. Sk_buff control methods are short and small to minimize system load. (Translated from article written by alancox)
. Alloc_skb () applies for a sk_buff and initializes it. The requested sk_buff is returned.
. Dev_alloc_skb () is similar to alloc_skb. After the buffer zone is applied, the 16-byte frame header space is retained. It is mainly used in Ethernet drivers.
. Kfree_skb () releases a sk_buff.
. Skb_clone () copies a sk_buff, but does not copy the data.
. Skb_copy () completely copies a sk_buff.
. Skb_dequeue () extracts the first element from a sk_buff linked list. Returns the retrieved sk_buff.
. Skb_dequeue () extracts the first element from a sk_buff linked list. The retrieved sk_buff is returned. If the linked list is empty, null is returned. This is a common operation.
. Skb_queue_head () puts an element in the header of A sk_buff linked list.
. Skb_queue_tail () puts an element at the end of a sk_buff linked list. This is also a common operation. Network data processing is mainly used to manage a first-in-first-out queue. skb_queue_tail () and skb_dequeue () are used to complete this task.
. Skb_insert () inserts an element before an element in the linked list.
. Skb_append () inserts an element after an element in the linked list. For some protocols (such as TCP), skb_insert () and skb_append () are used to reorganize data that do not arrive in sequence ().
. Skb_reserve () reserves a space in the buffer zone of the applied sk_buff. This space is generally used as the header space of the next layer of protocol.
. Skb_put () reserves a space for data in the buffer zone of the applied sk_buff. In
After alloc_skb, the buffer of the applied sk_buff is in the Free State. A tail Pointer Points to the free space. In fact, tail points to the buffer header at the beginning. Skb_reserve () applies for the protocol header space in the free space, and skb_put () applies for the data space. See the figure below.
. Skb_push () moves the data space in the sk_buff buffer forward. That is, the space in the head room is moved to the data area.
. Skb_pull () moves the space in the data area in the sk_buff buffer to the head room.
--------------------------------------------------
| Tail room (free) |
--------------------------------------------------
--------------------------------------------------
After alloc_skb ()
--------------------------------------------------
| Head room | tail room (free) |
--------------------------------------------------
After skb_reserve ()
--------------------------------------------------
| Head room | data area | tail room (free) |
--------------------------------------------------
After skb_put ()
--------------------------------------------------
| HEAD | SKB _ | data | tail room (free) |
| Room | push |
| Data area |
--------------------------------------------------
After skb_push ()
--------------------------------------------------
| HEAD | SKB _ | data area | tail room (free) |
| Pull |
| Pull |
| Head room |
--------------------------------------------------
After skb_pull ()
This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/zhoufanking/archive/2005/09/18/483927.aspx