文章目录
🔺【linux内核系列文章】
👉对一些文章内容进行了勘误,本系列文章长期不定时更新,希望能分享出优质的文章!
- 1、《linux内核数据结构分析之哈希表》
- 2、《一文总结linux内核通知链》
- 3、《linux内核中的debugfs》
- 4、《linux内核数据结构分析之链表》
- 5、《linux media子系统分析之media控制器设备》
- 6、《V4L2-PCI驱动程序样例分析(上)》
- 7、《v4l2框架分析之v4l2_fh》
- 8、《 v4l2框架分析之v4l2_subdev》
- 9、《 v4l2框架分析之v4l2_device》
- 10、《v4l2框架分析之video_device》
- 11、《linux内核重要函数 | do_initcalls》
- 12、《Linux设备驱动模型 | bus》
- 13、《linux内核裁剪随想》
- 14、《基于ARM64分析linux内核的链接脚本vmlinux.lds.S》
- 15、《linux内核start_kernel函数的早期操作》
- 16、《start_kernel函数详解系列之proc_caches_init》
- 17、《start_kernel函数详解系列之fork_init》
- 18、《start_kernel函数详解系列之rcu_init》
- 19、《start_kernel函数详解系列之proc_root_init》
- 20、《start_kernel详解系列之【setup_arch】》
- 21、《linux内核如何启动用户空间进程(上)》
- 22、《linux内核如何启动用户空间进程(下)》
- 23、《一文总结linux内核的完成量机制》
- 24、《一文总结linux内核设备驱动的注册和卸载》
- 25、《linux内核的启动加载程序的总结》
- 26、《linux内核入口:head.o》
- 27、《挂载根文件系统之rootfs》
- 28、《mount系统调用剖析》
- 29、《devtmpfs文件系统分析》
- 30、《linux内核的kthreadd线程》
- 31、《linux内核的进程调度—调度策略》
- 32、《linux系统调用实践(Arm架构)》
- 33、《对linux内核__init机制的实践》
- 34、《linux 内核中EXPORT_SYMBOL()分析与实践》
- 35、《linux内核如何挂载根文件系统》
- 36、《linux内核如何唤醒线程》
- 37、《linux内核的init线程》
- 38、《linux内核伪文件系统—sysfs分析》
- 39、《linux 内核设备模型的初始化(上)》
- 40、《linux 内核设备模型的初始化(下)》
- 41、《linux内核伪文件系统—proc分析》
- 42、《linux中断管理—workqueue工作队列》
- 43、《linux中断管理—软中断》
- 44、《linux中断管理 | tasklet》
- 45、《linux中断管理 | 中断管理框架(01)》
- 46、《linux内存管理 | 分配物理内存页面》
- 47、《linux内存管理 | 释放内存页面》
- 48、《对linux内核设备的注册机制和查找机制分析》
- 49、《linux内核设备驱动的注册机制》
linux源码相关文件:
- serial-core.c
- include/linux/serial_core.h
一、底层串行硬件驱动程序
底层串行硬件的驱动程序负责向serial核心驱动程序提供由struct uart_port
定义的端口信息和一组由struct uart_ops
定义的控制方法,底层驱动程序还负责处理端口的中断,并提供对控制台的支持。
二、Console支持
serial核心提供了一些助手函数:
uart_get_console()
识别正确的端口结构。uart_parse_options()
解析命令行参数。uart_console_write()
用于执行逐字符写入,将换行符转换为CRLF序列。在驱动程序编写的时候建议使用此函数,而不是实现新的写入接口。
三、锁支持
底层硬件驱动程序负责使用port->lock
执行必要的锁定。支持两把锁:一个是端口自旋锁,另一个是overall
信号量。从uart核心驱动程序的角度来看,port->lock
用于锁定以下的数据:
port->mctrl
port->icount
port->state->xmit.head (circ_buf->head)
port->state->xmit.tail (circ_buf->tail)
底层驱动程序可以自由地使用该锁来实现额外的锁定,port_mutex
互斥量用于防止在不适当的时间添加、删除或重新配置端口。
四、核心数据结构
1、struct uart_driver
struct uart_driver
结构表示具体UART驱动。该结构定义如下(/include/linux/serial_core.h):
struct uart_driver {
struct module *owner; //驱动模块的拥有者
const char *driver_name; //驱动名称
const char *dev_name; //设备名称
int major; //主设备号
int minor; //从设备号
int nr;
struct console *cons; //console
/*
* these are private; the low level driver should not
* touch these; they should be initialised to NULL
*/
struct uart_state *state; //uart状态
struct tty_driver *tty_driver; //描述ttydriver
};
2、struct uart_port
struct uart_port
表示一个具体的port,该结构定义如下(include/linux/serial_core.h):
struct uart_port {
spinlock_t lock; /* port 锁 */
unsigned long iobase; /* 输入/输出地址 */
unsigned char __iomem *membase; /* read/write[bwl] */
unsigned int (*serial_in)(struct uart_port *, int);
void (*serial_out)(struct uart_port *, int, int);
void (*set_termios)(struct uart_port *,
struct ktermios *new,
struct ktermios *old);
void (*set_mctrl)(struct uart_port *, unsigned int);
int (*startup)(struct uart_port *port);
void (*shutdown)(struct uart_port *port);
void (*throttle)(struct uart_port *port);
void (*unthrottle)(struct uart_port *port);
int (*handle_irq)(struct uart_port *);
void (*pm)(struct uart_port *, unsigned int state,
unsigned int old);
void (*handle_break)(struct uart_port *);
int (*rs485_config)(struct uart_port *,
struct serial_rs485 *rs485);
unsigned int irq; /* irq number */
unsigned long irqflags; /* irq flags */
unsigned int uartclk; /* base uart clock */
unsigned int fifosize; /* tx fifo size */
unsigned char x_char; /* xon/xoff char */
unsigned char regshift; /* reg offset shift */
unsigned char iotype; /* io access style */
unsigned char unused1;
unsigned int read_status_mask; /* driver specific */
unsigned int ignore_status_mask; /* driver specific */
struct uart_state *state; /* 指向父状态的指针 */
struct uart_icount icount; /* 通信信息 */
struct console *cons; /* struct console, if any */
#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(SUPPORT_SYSRQ)
unsigned long sysrq; /* sysrq timeout */
#endif
/* flags must be updated while holding port mutex */
upf_t flags;
#if __UPF_CHANGE_MASK > ASYNC_FLAGS
#error Change mask not equivalent to userspace-visible bit defines
#endif
/*
* Must hold termios_rwsem, port mutex and port lock to change;
* can hold any one lock to read.
*/
upstat_t status;
int hw_stopped; /* sw-assisted CTS flow state */
unsigned int mctrl; /* 当前调制解调器CTRL设置 */
unsigned int timeout; /* character-based timeout */
unsigned int type; /* port 类型 */
const struct uart_ops *ops;
unsigned int custom_divisor;