TTY Internals¶
Kopen¶
These functions serve for opening a TTY from the kernelspace:
-
void
tty_kclose
(struct tty_struct *tty)¶ closes tty opened by tty_kopen
Parameters
struct tty_struct *tty
- tty device
Description
Performs the final steps to release and free a tty device. It is the same as
tty_release_struct()
except that it also resets TTY_PORT_KOPENED
flag on
tty->port.
-
struct tty_struct *
tty_kopen_exclusive
(dev_t device)¶ open a tty device for kernel
Parameters
dev_t device
- dev_t of device to open
Description
Opens tty exclusively for kernel. Performs the driver lookup, makes sure it’s not already opened and performs the first-time tty initialization.
- Claims the global
tty_mutex
to serialize: - concurrent first-time tty initialization
- concurrent tty driver removal w/ lookup
- concurrent tty removal from driver table
Return
the locked initialized tty_struct
open a tty device for shared in-kernel use
Parameters
dev_t device
- dev_t of device to open
Description
Opens an already existing tty for in-kernel use. Compared to
tty_kopen_exclusive()
above it doesn’t ensure to be the only user.
Locking: identical to tty_kopen() above.
Exported Internal Functions¶
-
int
tty_dev_name_to_number
(const char *name, dev_t *number)¶ return dev_t for device name
Parameters
const char *name
- user space name of device under /dev
dev_t *number
- pointer to dev_t that this function will populate
Description
This function converts device names like ttyS0 or ttyUSB1 into dev_t like
(4, 64) or (188, 1). If no corresponding driver is registered then the
function returns -ENODEV
.
- Locking: this acquires tty_mutex to protect the tty_drivers list from
- being modified while we are traversing it, and makes sure to release it before exiting.
-
void
tty_release_struct
(struct tty_struct *tty, int idx)¶ release a tty struct
Parameters
struct tty_struct *tty
- tty device
int idx
- index of the tty
Description
Performs the final steps to release and free a tty device. It is roughly the
reverse of tty_init_dev()
.
-
int
tty_get_icount
(struct tty_struct *tty, struct serial_icounter_struct *icount)¶ get tty statistics
Parameters
struct tty_struct *tty
- tty device
struct serial_icounter_struct *icount
- output parameter
Description
Gets a copy of the tty’s icount statistics.
Locking: none (up to the driver)
Internal Functions¶
-
void
free_tty_struct
(struct tty_struct *tty)¶ free a disused tty
Parameters
struct tty_struct *tty
- tty struct to free
Description
Free the write buffers, tty queue and tty memory itself.
Locking: none. Must be called after tty is definitely unused
-
void
tty_free_file
(struct file *file)¶ free file->private_data
Parameters
struct file *file
- to free private_data of
Description
This shall be used only for fail path handling when tty_add_file was not called yet.
-
struct tty_driver *
get_tty_driver
(dev_t device, int *index)¶ find device of a tty
Parameters
dev_t device
- device identifier
int *index
- returns the index of the tty
Description
This routine returns a tty driver structure, given a device number and also passes back the index number.
Locking: caller must hold tty_mutex
-
struct file *
tty_release_redirect
(struct tty_struct *tty)¶ Release a redirect on a pty if present
Parameters
struct tty_struct *tty
- tty device
Description
This is available to the pty code so if the master closes, if the slave is a redirect it can release the redirect.
-
void
__tty_hangup
(struct tty_struct *tty, int exit_session)¶ actual handler for hangup events
Parameters
struct tty_struct *tty
- tty device
int exit_session
- if non-zero, signal all foreground group processes
Description
This can be called by a “kworker” kernel thread. That is process synchronous but doesn’t hold any locks, so we need to make sure we have the appropriate locks for what we’re doing.
The hangup event clears any pending redirections onto the hung up device. It ensures future writes will error and it does the needed line discipline hangup and signal delivery. The tty object itself remains intact.
- Locking:
- BTM
- redirect lock for undoing redirection
- file list lock for manipulating list of ttys
- tty_ldiscs_lock from called functions
- termios_rwsem resetting termios data
- tasklist_lock to walk task list for hangup event
- ->siglock to protect ->signal/->sighand
-
void
tty_vhangup_self
(void)¶ process vhangup for own ctty
Parameters
void
- no arguments
Description
Perform a vhangup on the current controlling tty
-
void
tty_vhangup_session
(struct tty_struct *tty)¶ hangup session leader exit
Parameters
struct tty_struct *tty
- tty to hangup
Description
The session leader is exiting and hanging up its controlling terminal.
Every process in the foreground process group is signalled SIGHUP
.
We do this synchronously so that when the syscall returns the process is complete. That guarantee is necessary for security reasons.
-
ssize_t
tty_read
(struct kiocb *iocb, struct iov_iter *to)¶ read method for tty device files
Parameters
struct kiocb *iocb
- kernel I/O control block
struct iov_iter *to
- destination for the data read
Description
Perform the read system call function on this terminal device. Checks for hung up devices before calling the line discipline method.
- Locking:
- Locks the line discipline internally while needed. Multiple read calls may be outstanding in parallel.
-
void
tty_write_message
(struct tty_struct *tty, char *msg)¶ write a message to a certain tty, not just the console.
Parameters
struct tty_struct *tty
- the destination tty_struct
char *msg
- the message to write
Description
This is used for messages that need to be redirected to a specific tty. We don’t put it into the syslog queue right now maybe in the future if really needed.
We must still hold the BTM and test the CLOSING flag for the moment.
-
ssize_t
tty_write
(struct kiocb *iocb, struct iov_iter *from)¶ write method for tty device file
Parameters
struct kiocb *iocb
- kernel I/O control block
struct iov_iter *from
- iov_iter with data to write
Description
Write data to a tty device via the line discipline.
- Locking:
- Locks the line discipline as required Writes to the tty driver are serialized by the atomic_write_lock and are then processed in chunks to the device. The line discipline write method will not be invoked in parallel for each device.
-
int
tty_send_xchar
(struct tty_struct *tty, char ch)¶ send priority character
Parameters
struct tty_struct *tty
- the tty to send to
char ch
- xchar to send
Description
Send a high priority character to the tty even if stopped.
Locking: none for xchar method, write ordering for write method.
-
void
pty_line_name
(struct tty_driver *driver, int index, char *p)¶ generate name for a pty
Parameters
struct tty_driver *driver
- the tty driver in use
int index
- the minor number
char *p
- output buffer of at least 6 bytes
Description
Generate a name from a driver reference and write it to the output buffer p.
Locking: None
-
ssize_t
tty_line_name
(struct tty_driver *driver, int index, char *p)¶ generate name for a tty
Parameters
struct tty_driver *driver
- the tty driver in use
int index
- the minor number
char *p
- output buffer of at least 7 bytes
Description
Generate a name from a driver reference and write it to the output buffer p.
Locking: None
-
struct tty_struct *
tty_driver_lookup_tty
(struct tty_driver *driver, struct file *file, int idx)¶ find an existing tty, if any
Parameters
struct tty_driver *driver
- the driver for the tty
struct file *file
- file object
int idx
- the minor number
Return
the tty, if found. If not found, return NULL
or ERR_PTR() if the
driver lookup() method returns an error.
Description
Locking: tty_mutex must be held. If the tty is found, bump the tty kref.
-
int
tty_driver_install_tty
(struct tty_driver *driver, struct tty_struct *tty)¶ install a tty entry in the driver
Parameters
struct tty_driver *driver
- the driver for the tty
struct tty_struct *tty
- the tty
Description
Install a tty object into the driver tables. The tty->index field will be set by the time this is called. This method is responsible for ensuring any need additional structures are allocated and configured.
Locking: tty_mutex for now
-
void
tty_driver_remove_tty
(struct tty_driver *driver, struct tty_struct *tty)¶ remove a tty from the driver tables
Parameters
struct tty_driver *driver
- the driver for the tty
struct tty_struct *tty
- tty to remove
Description
Remove a tty object from the driver tables. The tty->index field will be set by the time this is called.
Locking: tty_mutex for now
-
int
tty_reopen
(struct tty_struct *tty)¶ fast re-open of an open tty
Parameters
struct tty_struct *tty
- the tty to open
Description
Re-opens on master ptys are not allowed and return -EIO
.
Locking: Caller must hold tty_lock
Return
0 on success, -errno on error.
-
struct tty_struct *
tty_init_dev
(struct tty_driver *driver, int idx)¶ initialise a tty device
Parameters
struct tty_driver *driver
- tty driver we are opening a device on
int idx
- device index
Description
Prepare a tty device. This may not be a “new” clean device but could also be an active device. The pty drivers require special handling because of this.
- Locking:
- The function is called under the tty_mutex, which protects us from the tty struct or driver itself going away.
On exit the tty device has the line discipline attached and a reference count of 1. If a pair was created for pty/tty use and the other was a pty master then it too has a reference count of 1.
WSH 06/09/97: Rewritten to remove races and properly clean up after a failed open. The new code protects the open with a mutex, so it’s really quite straightforward. The mutex locking can probably be relaxed for the (most common) case of reopening a tty.
Return
new tty structure
-
void
tty_flush_works
(struct tty_struct *tty)¶ flush all works of a tty/pty pair
Parameters
struct tty_struct *tty
- tty device to flush works for (or either end of a pty pair)
Description
Sync flush all works belonging to tty (and the ‘other’ tty).
-
void
release_one_tty
(struct work_struct *work)¶ release tty structure memory
Parameters
struct work_struct *work
- work of tty we are obliterating
Description
Releases memory associated with a tty structure, and clears out the driver table slots. This function is called when a device is no longer in use. It also gets called when setup of a device fails.
- Locking:
- takes the file list lock internally when working on the list of ttys that the driver keeps.
This method gets called from a work queue so that the driver private cleanup ops can sleep (needed for USB at least)
-
void
release_tty
(struct tty_struct *tty, int idx)¶ release tty structure memory
Parameters
struct tty_struct *tty
- tty device release
int idx
- index of the tty device release
Description
Release both tty and a possible linked partner (think pty pair), and decrement the refcount of the backing module.
- Locking:
- tty_mutex takes the file list lock internally when working on the list of ttys that the driver keeps.
-
int
tty_release_checks
(struct tty_struct *tty, int idx)¶ check a tty before real release
Parameters
struct tty_struct *tty
- tty to check
int idx
- index of the tty
Description
Performs some paranoid checking before true release of the tty. This is a
no-op unless TTY_PARANOIA_CHECK
is defined.
-
int
tty_release
(struct inode *inode, struct file *filp)¶ vfs callback for close
Parameters
struct inode *inode
- inode of tty
struct file *filp
- file pointer for handle to tty
Description
Called the last time each file handle is closed that references this tty. There may however be several such references.
- Locking:
- Takes BKL. See tty_release_dev().
Even releasing the tty structures is a tricky business. We have to be very careful that the structures are all released at the same time, as interrupts might otherwise get the wrong pointers.
WSH 09/09/97: rewritten to avoid some nasty race conditions that could lead to double frees or releasing memory still in use.
-
struct tty_struct *
tty_open_current_tty
(dev_t device, struct file *filp)¶ get locked tty of current task
Parameters
dev_t device
- device number
struct file *filp
- file pointer to tty
Return
locked tty of the current task iff device is /dev/tty
Description
Performs a re-open of the current task’s controlling tty.
We cannot return driver and index like for the other nodes because devpts will not work then. It expects inodes to be from devpts FS.
-
struct tty_driver *
tty_lookup_driver
(dev_t device, struct file *filp, int *index)¶ lookup a tty driver for a given device file
Parameters
dev_t device
- device number
struct file *filp
- file pointer to tty
int *index
- index for the device in the return driver
Description
If returned value is not erroneous, the caller is responsible to decrement
the refcount by tty_driver_kref_put()
.
Locking: tty_mutex
protects get_tty_driver()
Return
driver for this inode (with increased refcount)
-
struct tty_struct *
tty_open_by_driver
(dev_t device, struct file *filp)¶ open a tty device
Parameters
dev_t device
- dev_t of device to open
struct file *filp
- file pointer to tty
Description
Performs the driver lookup, checks for a reopen, or otherwise performs the first-time tty initialization.
- Claims the global tty_mutex to serialize:
- concurrent first-time tty initialization
- concurrent tty driver removal w/ lookup
- concurrent tty removal from driver table
Return
the locked initialized or re-opened tty_struct
-
int
tty_open
(struct inode *inode, struct file *filp)¶ open a tty device
Parameters
struct inode *inode
- inode of device file
struct file *filp
- file pointer to tty
Description
tty_open()
and tty_release()
keep up the tty count that contains the number
of opens done on a tty. We cannot use the inode-count, as different inodes
might point to the same tty.
Open-counting is needed for pty masters, as well as for keeping track of serial lines: DTR is dropped when the last close happens. (This is not done solely through tty->count, now. - Ted 1/27/92)
The termios state of a pty is reset on the first open so that settings don’t persist across reuse.
- Locking:
tty_mutex
protects tty,tty_lookup_driver()
andtty_init_dev()
.- tty->count should protect the rest.
- ->siglock protects ->signal/->sighand
Note
the tty_unlock/lock cases without a ref are only safe due to tty_mutex
-
__poll_t
tty_poll
(struct file *filp, poll_table *wait)¶ check tty status
Parameters
struct file *filp
- file being polled
poll_table *wait
- poll wait structures to update
Description
Call the line discipline polling method to obtain the poll status of the device.
Locking: locks called line discipline but ldisc poll method may be re-entered freely by other callers.
-
int
tiocsti
(struct tty_struct *tty, char __user *p)¶ fake input character
Parameters
struct tty_struct *tty
- tty to fake input into
char __user *p
- pointer to character
Description
Fake input to a tty device. Does the necessary locking and input management.
FIXME: does not honour flow control ??
- Locking:
- Called functions take tty_ldiscs_lock
- current->signal->tty check is safe without locks
-
int
tiocgwinsz
(struct tty_struct *tty, struct winsize __user *arg)¶ implement window query ioctl
Parameters
struct tty_struct *tty
- tty
struct winsize __user *arg
- user buffer for result
Description
Copies the kernel idea of the window size into the user buffer.
Locking: tty->winsize_mutex is taken to ensure the winsize data is consistent.
-
int
tiocswinsz
(struct tty_struct *tty, struct winsize __user *arg)¶ implement window size set ioctl
Parameters
struct tty_struct *tty
- tty side of tty
struct winsize __user *arg
- user buffer for result
Description
Copies the user idea of the window size to the kernel. Traditionally this is just advisory information but for the Linux console it actually has driver level meaning and triggers a VC resize.
- Locking:
- Driver dependent. The default do_resize method takes the tty termios mutex and ctrl.lock. The console takes its own lock then calls into the default method.
-
int
tioccons
(struct file *file)¶ allow admin to move logical console
Parameters
struct file *file
- the file to become console
Description
Allow the administrator to move the redirected console device.
Locking: uses redirect_lock to guard the redirect information
-
int
tiocsetd
(struct tty_struct *tty, int __user *p)¶ set line discipline
Parameters
struct tty_struct *tty
- tty device
int __user *p
- pointer to user data
Description
Set the line discipline according to user request.
Locking: see tty_set_ldisc()
, this function is just a helper
-
int
tiocgetd
(struct tty_struct *tty, int __user *p)¶ get line discipline
Parameters
struct tty_struct *tty
- tty device
int __user *p
- pointer to user data
Description
Retrieves the line discipline id directly from the ldisc.
Locking: waits for ldisc reference (in case the line discipline is changing or the tty is being hungup)
-
int
send_break
(struct tty_struct *tty, unsigned int duration)¶ performed time break
Parameters
struct tty_struct *tty
- device to break on
unsigned int duration
- timeout in mS
Description
Perform a timed break on hardware that lacks its own driver level timed break functionality.
- Locking:
- tty->atomic_write_lock serializes
-
int
tty_tiocmget
(struct tty_struct *tty, int __user *p)¶ get modem status
Parameters
struct tty_struct *tty
- tty device
int __user *p
- pointer to result
Description
Obtain the modem status bits from the tty driver if the feature is
supported. Return -ENOTTY
if it is not available.
Locking: none (up to the driver)
-
int
tty_tiocmset
(struct tty_struct *tty, unsigned int cmd, unsigned __user *p)¶ set modem status
Parameters
struct tty_struct *tty
- tty device
unsigned int cmd
- command - clear bits, set bits or set all
unsigned __user *p
- pointer to desired bits
Description
Set the modem status bits from the tty driver if the feature
is supported. Return -ENOTTY
if it is not available.
Locking: none (up to the driver)
-
struct tty_struct *
alloc_tty_struct
(struct tty_driver *driver, int idx)¶ allocate a new tty
Parameters
struct tty_driver *driver
- driver which will handle the returned tty
int idx
- minor of the tty
Description
This subroutine allocates and initializes a tty structure.
Locking: none - tty in question is not exposed at this point