uart_close主要在tty_release和do_tty_hundup中调用,做与uart_pen相反的操作,具体源码如下:
/*
* In 2.4.5, calls to this will be serialized via the BKL in
* linux/drivers/char/tty_io.c:tty_release()
* linux/drivers/char/tty_io.c:do_tty_handup()
*/
static void uart_close(struct tty_struct *tty, struct file *filp)
{
struct uart_state *state = tty->driver_data; //uart_open中我们做的赋值
struct uart_port *port;
BUG_ON(!kernel_locked());
if (!state || !state->port)
return;
port = state->port;
pr_debug("uart_close(%d) called/n", port->line);
mutex_lock(&state->mutex);
if (tty_hung_up_p(filp))
goto done;
if ((tty->count == 1) && (state->count != 1)) {
/*
* Uh, oh. tty->count is 1, which means that the tty
* structure will be freed. state->count should always
* be one in these conditions. If it's greater than
* one, we've got real problems, since it means the
* serial port won't be shutdown.
*/
printk(KERN_ERR "uart_close: bad serial port count; tty->count is 1, "
"state->count is %d/n", state->count);
state->count = 1;
}
if (--state->count < 0) {
printk(KERN_ERR "uart_close: bad serial port count for %s: %d/n",
tty->name, state->count);
state->count = 0;
}
//只有state->count 为0才说明此外没有对串口的操作可以关闭串口
if (state->count)
goto done;
/*
* Now we wait for the transmit buffer to clear; and we notify
* the line discipline to only process XON/XOFF characters by
* setting tty->closing.
*/
tty->closing = 1;
//在关闭之前先把缓存中或者待发送的数据先发送完,这里先唤醒写等待队列,然后调用wait_until_sent发送数据
//该函数主要将数据发射出去
if (state->closing_wait != USF_CLOSING_WAIT_NONE)
tty_wait_until_sent(tty, msecs_to_jiffies(state->closing_wait));
/*
* At this point, we stop accepting input. To do this, we
* disable the receive line status interrupts.
*/
if (state->info.flags & UIF_INITIALIZED) {
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
port->ops->stop_rx(port); //停止发送数据
spin_unlock_irqrestore(&port->lock, flags);
/*
* Before we drop DTR, make sure the UART transmitter
* has completely drained; this is especially
* important if there is a transmit FIFO!
*/
uart_wait_until_sent(tty, port->timeout);
}
//清除一些标志,释放串口资源
uart_shutdown(state);
//对发送缓存及其标志做清理
uart_flush_buffer(tty);
//对线路规程中的数据做清理
tty_ldisc_flush(tty);
tty->closing = 0;
state->info.port.tty = NULL;
//若有其他进程在等待打开次串口,先等待一段时间,然后清理打开标志,并在最后唤醒等待的进程
if (state->info.port.blocked_open) {
if (state->close_delay)
msleep_interruptible(state->close_delay);
} else if (!uart_console(port)) {
uart_change_pm(state, 3);
}
/*
* Wake up anyone trying to open this port.
*/
state->info.flags &= ~UIF_NORMAL_ACTIVE;
wake_up_interruptible(&state->info.port.open_wait);
done:
mutex_unlock(&state->mutex);
}