linux kernel container_of 是什么
时间: 2024-05-19 07:14:39 浏览: 13
container_of 是一个宏定义,用于从某个结构体类型的成员指针中获取包含该成员的结构体的指针。在 Linux 内核中,container_of 宏的定义如下:
#define container_of(ptr, type, member) \
((type *)((char *)(ptr) - offsetof(type, member)))
其中,ptr 表示某个结构体类型的成员指针,type 表示包含该成员的结构体类型,member 表示该成员在结构体中的名称。该宏会先通过 offsetof 宏获取 member 成员在 type 结构体中的偏移量,然后将 ptr 强制转换为 char* 类型,并从偏移量位置开始向前移动,最终得到包含该成员的 type 结构体的指针。
在 Linux 内核中,container_of 宏通常用于实现链表数据结构。例如,一个链表节点结构体包含一个指向下一个节点的指针,可以通过 container_of 宏获取包含该节点的结构体的指针,从而实现对整个链表的遍历和操作。
相关问题
linux 内核 container_of
在Linux内核中,container_of是一个宏定义,用于获取包含某个成员的结构体变量的地址。它的定义可以在include/linux/kernel.h中找到。该宏的作用是通过给定的成员指针,返回包含该成员的结构体变量的地址。具体的定义如下:
```c
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
```
这个宏的使用非常方便,可以通过成员指针来获取整个结构体变量的地址。在进行内核驱动开发时,经常会用到这个宏来获取结构体变量的地址,以便进行相关操作。
#### 引用[.reference_title]
- *1* [Linux内核:理解container_of宏](https://blog.csdn.net/qq_28877125/article/details/124209504)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item]
- *2* *3* [Linux内核中container_of的原理及其使用详解](https://blog.csdn.net/u010632165/article/details/107523477)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item]
[ .reference_list ]
请提供Linux kernel 4.14 AXI UART 16550 driver完整源代码
以下是 Linux kernel 4.14 中 AXI UART 16550 驱动程序的完整源代码,供参考:
```c
/*
* AXI 16550 UART driver
*/
#include <linux/clk.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/serial_core.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/tty_port.h>
#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
#define XUARTPS_CR_STOPBRK 0x00000001 /* Stop transmitter break */
#define XUARTPS_CR_STARTBRK 0x00000002 /* Start transmitter break */
#define XUARTPS_CR_TORST 0x00000008 /* Transmit out-of-band reset */
#define XUARTPS_CR_TX_DIS 0x00000010 /* Transmit disable */
#define XUARTPS_CR_TX_EN 0x00000020 /* Transmit enable */
#define XUARTPS_CR_RX_DIS 0x00000040 /* Receive disable */
#define XUARTPS_CR_RX_EN 0x00000080 /* Receive enable */
/* RS485 support */
#define AXI_RS485_ENABLED (1 << 0)
#define AXI_RS485_RTS_ACTIVE_HIGH (1 << 1)
#define AXI_RS485_RX_DURING_TX (1 << 2)
/* AXI UART 16550 registers */
struct axi_uart16550 {
u32 rxfifo;
u32 txdata;
u32 ctrl;
u32 intr_enable;
u32 intr_status;
u32 baud_rate_gen;
u32 rcv_timeout;
u32 flow_ctrl;
u32 mode;
};
/* AXI UART 16550 driver data */
struct axi_uart16550_data {
struct uart_port port;
struct clk *clk;
void __iomem *regs;
struct tty_port tty_port;
unsigned int ns16550_irq;
spinlock_t lock;
u32 ctrl_reg;
unsigned int rs485_flags;
};
/* AXI UART 16550 driver functions */
static void axi_uart16550_set_mctrl(struct uart_port *port, u_int mctrl)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
unsigned long flags;
spin_lock_irqsave(&data->lock, flags);
if (mctrl & TIOCM_RTS) {
if (data->rs485_flags & AXI_RS485_ENABLED) {
if (data->rs485_flags & AXI_RS485_RTS_ACTIVE_HIGH)
data->ctrl_reg |= XUARTPS_CR_TX_EN;
else
data->ctrl_reg &= ~XUARTPS_CR_TX_EN;
} else {
data->ctrl_reg |= XUARTPS_CR_TX_EN;
}
} else {
data->ctrl_reg &= ~XUARTPS_CR_TX_EN;
}
if (mctrl & TIOCM_DTR) {
data->ctrl_reg |= XUARTPS_CR_RX_EN;
} else {
data->ctrl_reg &= ~XUARTPS_CR_RX_EN;
}
writel(data->ctrl_reg, data->regs + offsetof(struct axi_uart16550, ctrl));
spin_unlock_irqrestore(&data->lock, flags);
}
static u_int axi_uart16550_get_mctrl(struct uart_port *port)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
unsigned long flags;
u_int status = 0;
spin_lock_irqsave(&data->lock, flags);
if (data->ctrl_reg & XUARTPS_CR_TX_EN)
status |= TIOCM_RTS;
if (data->ctrl_reg & XUARTPS_CR_RX_EN)
status |= TIOCM_DTR;
spin_unlock_irqrestore(&data->lock, flags);
return status;
}
static void axi_uart16550_stop_tx(struct uart_port *port)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
unsigned long flags;
spin_lock_irqsave(&data->lock, flags);
data->ctrl_reg &= ~XUARTPS_CR_TX_EN;
writel(data->ctrl_reg, data->regs + offsetof(struct axi_uart16550, ctrl));
spin_unlock_irqrestore(&data->lock, flags);
}
static void axi_uart16550_start_tx(struct uart_port *port)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
unsigned long flags;
spin_lock_irqsave(&data->lock, flags);
if (data->rs485_flags & AXI_RS485_ENABLED) {
if (data->rs485_flags & AXI_RS485_RX_DURING_TX)
data->ctrl_reg |= XUARTPS_CR_RX_EN;
else
data->ctrl_reg &= ~XUARTPS_CR_RX_EN;
if (data->rs485_flags & AXI_RS485_RTS_ACTIVE_HIGH)
data->ctrl_reg |= XUARTPS_CR_TX_EN;
else
data->ctrl_reg &= ~XUARTPS_CR_TX_EN;
} else {
data->ctrl_reg |= XUARTPS_CR_TX_EN;
data->ctrl_reg |= XUARTPS_CR_RX_EN;
}
writel(data->ctrl_reg, data->regs + offsetof(struct axi_uart16550, ctrl));
spin_unlock_irqrestore(&data->lock, flags);
}
static void axi_uart16550_stop_rx(struct uart_port *port)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
unsigned long flags;
spin_lock_irqsave(&data->lock, flags);
data->ctrl_reg &= ~XUARTPS_CR_RX_EN;
writel(data->ctrl_reg, data->regs + offsetof(struct axi_uart16550, ctrl));
spin_unlock_irqrestore(&data->lock, flags);
}
static void axi_uart16550_enable_ms(struct uart_port *port)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
data->ctrl_reg |= XUARTPS_CR_RX_EN | XUARTPS_CR_TX_EN;
writel(data->ctrl_reg, data->regs + offsetof(struct axi_uart16550, ctrl));
}
static void axi_uart16550_break_ctl(struct uart_port *port, int break_state)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
if (break_state == -1) {
data->ctrl_reg &= ~XUARTPS_CR_STARTBRK;
data->ctrl_reg |= XUARTPS_CR_STOPBRK;
} else if (break_state == 1) {
data->ctrl_reg |= XUARTPS_CR_STARTBRK;
data->ctrl_reg &= ~XUARTPS_CR_STOPBRK;
}
writel(data->ctrl_reg, data->regs + offsetof(struct axi_uart16550, ctrl));
}
static int axi_uart16550_startup(struct uart_port *port)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
int ret;
/* Enable clock */
ret = clk_prepare_enable(data->clk);
if (ret < 0) {
dev_err(port->dev, "failed to enable clock: %d\n", ret);
return ret;
}
/* Initialize port */
uart_port_set_ops(port, &serial8250_ops);
port->flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
port->iotype = UPIO_MEM;
port->regshift = 2;
port->mapbase = (unsigned long)data->regs;
port->type = PORT_16550A;
port->irq = data->ns16550_irq;
spin_lock_init(&data->lock);
tty_port_init(&data->tty_port);
port->private_data = &data->tty_port;
/* Register port */
ret = uart_add_one_port(&serial8250_reg, port);
if (ret < 0) {
dev_err(port->dev, "failed to register port: %d\n", ret);
clk_disable_unprepare(data->clk);
return ret;
}
/* Enable IRQ */
writel(0xff, data->regs + offsetof(struct axi_uart16550, intr_enable));
return 0;
}
static void axi_uart16550_shutdown(struct uart_port *port)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
/* Disable IRQ */
writel(0x00, data->regs + offsetof(struct axi_uart16550, intr_enable));
/* Unregister port */
uart_remove_one_port(&serial8250_reg, port);
/* Free resources */
clk_disable_unprepare(data->clk);
}
static int axi_uart16550_request_port(struct uart_port *port)
{
return 0;
}
static void axi_uart16550_config_port(struct uart_port *port, int flags)
{
struct axi_uart16550_data *data = container_of(port, struct axi_uart16550_data, port);
unsigned long baud_divisor;
u32 mode_reg = 0;
/* Set baud rate */
baud_divisor = uart_get_baud_rate(port, flags, port->uartclk, 115200, 4000000);
uart_update_timeout(port, baud_divisor, 115200);
writel(baud_divisor, data->regs + offsetof(struct axi_uart16550, baud_rate_gen));
/* Set data format */
mode_reg |= (3 << 0); /* 8 data bits */
mode_reg |= (0 << 3); /* 1 stop bit */
mode_reg |= (0 << 4); /* no parity */
mode_reg |= (0 << 6); /* no break */
writel(mode_reg, data->regs + offsetof(struct axi_uart16550, mode));
}
static void axi_uart16550_release_port(struct uart_port *port)
{
/* Do nothing */
}
static const struct uart_ops axi_uart16550_ops = {
.tx_empty = serial8250_tx_empty,
.set_mctrl = axi_uart16550_set_mctrl,
.get_mctrl = axi_uart16550_get_mctrl,
.stop_tx = axi_uart16550_stop_tx,
.start_tx = axi_uart16550_start_tx,
.stop_rx = axi_uart16550_stop_rx,
.enable_ms = axi_uart16550_enable_ms,
.break_ctl = axi_uart16550_break_ctl,
.startup = axi_uart16550_startup,
.shutdown = axi_uart16550_shutdown,
.flush_buffer = serial8250_clear_and_reinit_fifos,
.set_termios = serial8250_set_termios,
.type = serial8250_type,
.release_port = axi_uart16550_release_port,
.request_port = axi_uart16550_request_port,
.config_port = axi_uart16550_config_port,
};
/* AXI UART 16550 driver initialization */
static int axi_uart16550_probe(struct platform_device *pdev)
{
struct
相关推荐
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)