首页 > 系统相关 >linux驱动移植-UART设备驱动

linux驱动移植-UART设备驱动

时间:2023-03-06 23:11:59浏览次数:57  
标签:tty struct UART driver uart state linux 驱动 port

----------------------------------------------------------------------------------------------------------------------------
内核版本:linux 5.2.8
根文件系统:busybox 1.25.0
u-boot:2016.05
----------------------------------------------------------------------------------------------------------------------------

一、UART驱动框架

UART设备驱动框架如下图所示:

上图展示了四种注册uart设备驱动的方式,分别别位case A到case D。

二、UART核心数据结构

学习uart驱动,首先要了解驱动框架涉及到的数据结构,知道每个数据结构以及成员的含义之后,再去看源码就容易了。

2.1 struct uart_driver

每一款SoC的UART都需要去实现并定义个属于它自己uart_driver结构,uart_driver包含了串口设备名,串口驱动名,主次设备号,串口控制台(可选))等信息,还封装了tty_driver,定义在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;

        /*
         * these are private; the low level driver should not
         * touch these; they should be initialised to NULL
         */
        struct uart_state       *state;
        struct tty_driver       *tty_driver;
};

其中部分参数含义如下:

  • owner:这个驱动的模块拥有者;
  • driver_name:串口驱动的名称;
  • dev_name:串口设备的名称;
  • major:主设备号;
  • minor:次设备号;
  • nr:该驱动支持的串口数量;比如,某某芯片的介绍:”多达3个UART接口“,那么这个nr指的就是这个3;
  • cons:其对应的console,若该uart_driver支持serial console;否则为NULL;
  • state:下层,串口驱动层;指向一个数组,对应了芯片的每一个UART(比如 uart_state[0] 对应了芯片的 UART0以此类推),需要初始化为NULL;
  • tty_driver:上层,tty驱动层;需要初始化为NULL;、

2.2 struct console

struct console用于实现控制台打印功能,定义在include/linux/console.h:

struct console {
        char    name[16];
        void    (*write)(struct console *, const char *, unsigned);
        int     (*read)(struct console *, char *, unsigned);
        struct tty_driver *(*device)(struct console *, int *);
        void    (*unblank)(void);
        int     (*setup)(struct console *, char *);
        int     (*match)(struct console *, char *name, int idx, char *options);
        short   flags;
        short   index;
        int     cflag;
        void    *data;
        struct   console *next;
};

其中部分参数含义如下:

  • name:控制台名称;
  • write:写函数;
  • read:读函数;
  • device:
  • unblank:
  • setup:
  • match:
  • flags:
  • index:
  • pflag:
  • data:
  • next:

2.3 struct uart_state

每一个uart端口对应着一个uart_state,该结构体将uart_port与对应的circ_buf联系起来。uart_state有两个成员在底层串口驱动会用到:xmit和port。

用户空间程序通过串口发送数据时,上层驱动将用户数据保存在xmit;而串口发送中断处理函数就是通过xmit获取到用户数据并将它们发送出去。

串口接收中断处理函数需要通过port将接收到的数据传递给线路规程层。定义在include/linux/serial_core.h:

/*
 * This is the state information which is persistent across opens.
 */
struct uart_state {
        struct tty_port         port;

        enum uart_pm_state      pm_state;
        struct circ_buf         xmit;

        atomic_t                refcount;
        wait_queue_head_t       remove_wait;
        struct uart_port        *uart_port;
};

其中部分参数含义如下:

  • port:tty port;
  • pm_state:
  • xmit:串口待发送数据环形缓冲区;
  • refcount:
  • remove_wait:
  • uart_port:uart port;

2.4 struct uart_port

uart_port存储的是与UART串口硬件相关的信息,需要芯片厂家定义自己的 uart_port 结构并填充它,该结构定义在include/linux/serial_core.h:

struct uart_port {
        spinlock_t              lock;                   /* port lock */
        unsigned long           iobase;                 /* in/out[bwl] */
        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_ldisc)(struct uart_port *,
                                             struct ktermios *);
        unsigned int            (*get_mctrl)(struct uart_port *);
        void                    (*set_mctrl)(struct uart_port *, unsigned int);
        unsigned int            (*get_divisor)(struct uart_port *,
                                               unsigned int baud,
                                               unsigned int *frac);
        void                    (*set_divisor)(struct uart_port *,
                                               unsigned int baud,
                                               unsigned int quot,
                                               unsigned int quot_frac);
        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);
        int                     (*iso7816_config)(struct uart_port *,
                                                  struct serial_iso7816 *iso7816);
        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           quirks;                 /* internal quirks */

#define UPIO_PORT               (SERIAL_IO_PORT)        /* 8b I/O port access */
#define UPIO_HUB6               (SERIAL_IO_HUB6)        /* Hub6 ISA card */
#define UPIO_MEM                (SERIAL_IO_MEM)         /* driver-specific */
#define UPIO_MEM32              (SERIAL_IO_MEM32)       /* 32b little endian */
#define UPIO_AU                 (SERIAL_IO_AU)          /* Au1x00 and RT288x type IO */
#define UPIO_TSI                (SERIAL_IO_TSI)         /* Tsi108/109 type IO */
#define UPIO_MEM32BE            (SERIAL_IO_MEM32BE)     /* 32b big endian */
#define UPIO_MEM16              (SERIAL_IO_MEM16)       /* 16b little endian */

        /* quirks must be updated while holding port mutex */
#define UPQ_NO_TXEN_TEST        BIT(0)

        unsigned int            read_status_mask;       /* driver specific */
        unsigned int            ignore_status_mask;     /* driver specific */
        struct uart_state       *state;                 /* pointer to parent state */
        struct uart_icount      icount;                 /* statistics */

        struct console          *cons;                  /* struct console, if any */
#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(SUPPORT_SYSRQ)
        unsigned long           sysrq;                  /* sysrq timeout */
        unsigned int            sysrq_ch;               /* char for sysrq */
#endif
        /*
         * These flags must be equivalent to the flags defined in
         * include/uapi/linux/tty_flags.h which are the userspace definitions
         * assigned from the serial_struct flags in uart_set_info()
         * [for bit definitions in the UPF_CHANGE_MASK]
         *
         * Bits [0..UPF_LAST_USER] are userspace defined/visible/changeable
         * The remaining bits are serial-core specific and not modifiable by
         * userspace.
         */
#define UPF_FOURPORT            ((__force upf_t) ASYNC_FOURPORT       /* 1  */ )
#define UPF_SAK                 ((__force upf_t) ASYNC_SAK            /* 2  */ )
#define UPF_SPD_HI              ((__force upf_t) ASYNC_SPD_HI         /* 4  */ )
#define UPF_SPD_VHI             ((__force upf_t) ASYNC_SPD_VHI        /* 5  */ )
#define UPF_SPD_CUST            ((__force upf_t) ASYNC_SPD_CUST   /* 0x0030 */ )
#define UPF_SPD_WARP            ((__force upf_t) ASYNC_SPD_WARP   /* 0x1010 */ )
#define UPF_SPD_MASK            ((__force upf_t) ASYNC_SPD_MASK   /* 0x1030 */ )
#define UPF_SKIP_TEST           ((__force upf_t) ASYNC_SKIP_TEST      /* 6  */ )
#define UPF_AUTO_IRQ            ((__force upf_t) ASYNC_AUTO_IRQ       /* 7  */ )
#define UPF_HARDPPS_CD          ((__force upf_t) ASYNC_HARDPPS_CD     /* 11 */ )
#define UPF_SPD_SHI             ((__force upf_t) ASYNC_SPD_SHI        /* 12 */ )
#define UPF_LOW_LATENCY         ((__force upf_t) ASYNC_LOW_LATENCY    /* 13 */ )
#define UPF_BUGGY_UART          ((__force upf_t) ASYNC_BUGGY_UART     /* 14 */ )
#define UPF_MAGIC_MULTIPLIER    ((__force upf_t) ASYNC_MAGIC_MULTIPLIER /* 16 */ )

#define UPF_NO_THRE_TEST        ((__force upf_t) (1 << 19))
/* Port has hardware-assisted h/w flow control */
#define UPF_AUTO_CTS            ((__force upf_t) (1 << 20))
#define UPF_AUTO_RTS            ((__force upf_t) (1 << 21))
#define UPF_HARD_FLOW           ((__force upf_t) (UPF_AUTO_CTS | UPF_AUTO_RTS))
/* Port has hardware-assisted s/w flow control */
#define UPF_SOFT_FLOW           ((__force upf_t) (1 << 22))
#define UPF_CONS_FLOW           ((__force upf_t) (1 << 23))
#define UPF_SHARE_IRQ           ((__force upf_t) (1 << 24))
#define UPF_EXAR_EFR            ((__force upf_t) (1 << 25))
#define UPF_BUG_THRE            ((__force upf_t) (1 << 26))
/* The exact UART type is known and should not be probed.  */
#define UPF_FIXED_TYPE          ((__force upf_t) (1 << 27))
#define UPF_BOOT_AUTOCONF       ((__force upf_t) (1 << 28))
#define UPF_FIXED_PORT          ((__force upf_t) (1 << 29))
#define UPF_DEAD                ((__force upf_t) (1 << 30))
#define UPF_IOREMAP             ((__force upf_t) (1 << 31))

#define __UPF_CHANGE_MASK       0x17fff
#define UPF_CHANGE_MASK         ((__force upf_t) __UPF_CHANGE_MASK)
#define UPF_USR_MASK            ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY))

#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;

#define UPSTAT_CTS_ENABLE       ((__force upstat_t) (1 << 0))
#define UPSTAT_DCD_ENABLE       ((__force upstat_t) (1 << 1))
#define UPSTAT_AUTORTS          ((__force upstat_t) (1 << 2))
#define UPSTAT_AUTOCTS          ((__force upstat_t) (1 << 3))
#define UPSTAT_AUTOXOFF         ((__force upstat_t) (1 << 4))
#define UPSTAT_SYNC_FIFO        ((__force upstat_t) (1 << 5))

        int                     hw_stopped;             /* sw-assisted CTS flow state */
        unsigned int            mctrl;                  /* current modem ctrl settings */
        unsigned int            timeout;                /* character-based timeout */
        unsigned int            type;                   /* port type */
        const struct uart_ops   *ops;
        unsigned int            custom_divisor;
        unsigned int            line;                   /* port index */
        unsigned int            minor;
        resource_size_t         mapbase;                /* for ioremap */
        resource_size_t         mapsize;
        struct device           *dev;                   /* parent device */
        unsigned char           hub6;                   /* this should be in the 8250 driver */
        unsigned char           suspended;
        unsigned char           unused[2];
        const char              *name;                  /* port name */
        struct attribute_group  *attr_group;            /* port specific attributes */
        const struct attribute_group **tty_groups;      /* all attributes (serial core use only) */
        struct serial_rs485     rs485;
        struct serial_iso7816   iso7816;
        void                    *private_data;          /* generic platform data pointer */
};

其中部分参数含义如下:

  • iobase:I/O端口寄存器基地址,物理地址;
  • membase:I/O端口寄存器基地址,虚拟地址;
  • irq:中断号;
  • irqflags:中断标志;
  • uartclk:串口时钟;
  • fifosize:串口缓冲区大小;
  • regshift:寄存器位移;
  • iotype:I/O访问方式;
  • icount:串口信息计数器;
  • type:端口类型;
  • ops:串口端口的操作函数;
  • line:端口索引;
  • mapbase:I/O内存物理基地址;
  • dev:设备模型中的设备;

2.5 struct uart_ops

uart_ops定义了UART硬件相关相关的操作集,芯片厂家需要进行硬件寄存器级的适配其中各个操作,该结构定义在include/linux/serial_core.h:

/*
 * This structure describes all the operations that can be done on the
 * physical hardware.  See Documentation/serial/driver.rst for details.
 */
struct uart_ops {
        unsigned int    (*tx_empty)(struct uart_port *);
        void            (*set_mctrl)(struct uart_port *, unsigned int mctrl);
        unsigned int    (*get_mctrl)(struct uart_port *);
        void            (*stop_tx)(struct uart_port *);
        void            (*start_tx)(struct uart_port *);
        void            (*throttle)(struct uart_port *);
        void            (*unthrottle)(struct uart_port *);
        void            (*send_xchar)(struct uart_port *, char ch);
        void            (*stop_rx)(struct uart_port *);
        void            (*enable_ms)(struct uart_port *);
        void            (*break_ctl)(struct uart_port *, int ctl);
        int             (*startup)(struct uart_port *);
        void            (*shutdown)(struct uart_port *);
        void            (*flush_buffer)(struct uart_port *);
        void            (*set_termios)(struct uart_port *, struct ktermios *new,
                                       struct ktermios *old);
        void            (*set_ldisc)(struct uart_port *, struct ktermios *);
        void            (*pm)(struct uart_port *, unsigned int state,
                              unsigned int oldstate);

        /*
         * Return a string describing the type of the port
         */
        const char      *(*type)(struct uart_port *);

        /*
         * Release IO and memory resources used by the port.
         * This includes iounmap if necessary.
         */
        void            (*release_port)(struct uart_port *);

        /*
         * Request IO and memory resources used by the port.
         * This includes iomapping the port if necessary.
         */
        int             (*request_port)(struct uart_port *);
        void            (*config_port)(struct uart_port *, int);
        int             (*verify_port)(struct uart_port *, struct serial_struct *);
        int             (*ioctl)(struct uart_port *, unsigned int, unsigned long);
#ifdef CONFIG_CONSOLE_POLL
        int             (*poll_init)(struct uart_port *);
        void            (*poll_put_char)(struct uart_port *, unsigned char);
        int             (*poll_get_char)(struct uart_port *);
#endif
};

其中部分参数含义如下:

  • tx_empty:串口的Tx FIFO是否为空;
  • set_mctrl:设置串口modem控制;
  • get_mctrl:获取串口modem控制;
  • stop_tx:停止串口数据发送;
  • start_tx:开始串口数据发送;
  • send_xchar:发送一个字符;
  • stop_rx:停止串口数据接收;
  • enable_ms:使能modem的状态信号;
  • break_ctl:设置break信号;
  • startup:启动串口,应用程序打开串口的设备文件时,该函数被调用;
  • shutdown:关闭串口,应用程序关闭串口的设备文件时,该函数被调用;
  • set_termios:设置串口参数;
  • set_ldisc:设置线路规程;
  • pm:串口电源管理;
  • request_port:申请必要的IO端口/IO内存资源,必要时还可以重新映射串口端口;
  • config_port:指向串口所需的自动配置;
  • verify_port:核实新串口的信息;

三、UART驱动API

linux内核提供了一组函数用于操作uart_driver和uart_port。

3.1 注册UART驱动

uart_register_driver用于注册UART设备,函数定义在drivers/tty/serial/serial_core.c:

/**
 *      uart_register_driver - register a driver with the uart core layer
 *      @drv: low level driver structure
 *
 *      Register a uart driver with the core driver.  We in turn register
 *      with the tty layer, and initialise the core driver per-port state.
 *
 *      We have a proc file in /proc/tty/driver which is named after the
 *      normal driver.
 *
 *      drv->port should be NULL, and the per-port structures should be
 *      registered using uart_add_one_port after this call has succeeded.
 */
int uart_register_driver(struct uart_driver *drv)
{
        struct tty_driver *normal;
        int i, retval = -ENOMEM;

        BUG_ON(drv->state);

        /*
         * Maybe we should be using a slab cache for this, especially if
         * we have a large number of ports to handle.
         */
        drv->state = kcalloc(drv->nr, sizeof(struct uart_state), GFP_KERNEL);  // 申请内存,支持几个串口,就申请几个uart_state结构体
        if (!drv->state)
                goto out;

        normal = alloc_tty_driver(drv->nr);    // 分配tty驱动
        if (!normal)
                goto out_kfree;

        drv->tty_driver = normal;
     // 初始化tty驱动成员  
        normal->driver_name     = drv->driver_name;
        normal->name            = drv->dev_name;
        normal->major           = drv->major;
        normal->minor_start     = drv->minor;
        normal->type            = TTY_DRIVER_TYPE_SERIAL;
        normal->subtype         = SERIAL_TYPE_NORMAL;
        normal->init_termios    = tty_std_termios;
        normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
        normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600;
        normal->flags           = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
        normal->driver_state    = drv;
        tty_set_operations(normal, &uart_ops);  // 初始化tty driver操作集
        /*
         * Initialise the UART state(s).
         */
        for (i = 0; i < drv->nr; i++) {
                struct uart_state *state = drv->state + i;
                struct tty_port *port = &state->port;

                tty_port_init(port);  // 初始化tty port
                port->ops = &uart_port_ops;
        }

        retval = tty_register_driver(normal);  // 注册tty驱动
        if (retval >= 0)   // 成功返回0
                return retval;

        for (i = 0; i < drv->nr; i++)
                tty_port_destroy(&drv->state[i].port);
        put_tty_driver(normal);  
out_kfree:
        kfree(drv->state);
out:
        return retval;
}

该函数的入参是struct uart_driver,该函主要:

  • 首先初始化uart_driver的成员:
    • 根据驱动支持的串口数量,动态申请内存,初始化state成员,执行一个数组,每个成员都是uart_state,用来存放驱动所支持的串口(端口)的物理信息;;
    • 根据驱动支持的串口数量,分配tty驱动,初始化tty_driver成员;
  • 初始化tty驱动:
    • 设置驱动名称driver_name;
    • 设置设备名称name;
    • 设置主设备号major;
    • 设置开始的次设备号minor_start;
    • 设置tty驱动类型为TTY_DRIVER_TYPE_SERIAL;
    • 设置tty驱动子类型为SERIAL_TYPE_NORMAL;
    • 设置初始化线路设置iit_termios;
    • 设置tty驱动标志为TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
    • 设置tty驱动私有数据为uart_driver;
    • 设置tty驱动操作集合ops为uart_ops;
  • 遍历state数组,依次初始化为一个uart_state:
    • 获取成员port,类型为tty_port,调用tty_port_init初始化;
    • 设置tty port操作集为uart_port_ops;
  • 调用tty_register_driver注册tty驱动;

通过这段源码解读,我们会发现uart_driver的注册,实际上就是tty_driver的注册,都是将uart的参数传递给tty_driver,后注册字符设备、分配设备文件、将驱动注册到tty_driver链表中。

3.2 注册uart_port

 

在 uart_register_driver 调用成功后,可以说,我们已经对uart_drvier进行了注册,并且实现了这个结构体中的绝大多数成员了,此刻,还需要调用uart_add_one_port 结构来向已经注册进内核的uart_drvier赋其生命;uart_add_one_port函数定义在drivers/tty/serial/serial_core.c:

/**
 *      uart_add_one_port - attach a driver-defined port structure
 *      @drv: pointer to the uart low level driver structure for this port
 *      @uport: uart port structure to use for this port.
 *
 *      This allows the driver to register its own uart_port structure
 *      with the core driver.  The main purpose is to allow the low
 *      level uart drivers to expand uart_port, rather than having yet
 *      more levels of structures.
 */
int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
{
        struct uart_state *state;
        struct tty_port *port;
        int ret = 0;
        struct device *tty_dev;
        int num_groups;

        BUG_ON(in_interrupt());

        if (uport->line >= drv->nr)
                return -EINVAL;

        state = drv->state + uport->line;
        port = &state->port;

        mutex_lock(&port_mutex);
        mutex_lock(&port->mutex);
        if (state->uart_port) {
                ret = -EINVAL;
                goto out;
        }

        /* Link the port to the driver state table and vice versa */
        atomic_set(&state->refcount, 1);
        init_waitqueue_head(&state->remove_wait);
        state->uart_port = uport;
        uport->state = state;

        state->pm_state = UART_PM_STATE_UNDEFINED;
        uport->cons = drv->cons;
        uport->minor = drv->tty_driver->minor_start + uport->line;
        uport->name = kasprintf(GFP_KERNEL, "%s%d", drv->dev_name,
                                drv->tty_driver->name_base + uport->line);
        if (!uport->name) {
                ret = -ENOMEM;
                goto out;
        }

        /*
         * If this port is a console, then the spinlock is already
         * initialised.
         */
        if (!(uart_console(uport) && (uport->cons->flags & CON_ENABLED))) {
                spin_lock_init(&uport->lock);
                lockdep_set_class(&uport->lock, &port_lock_key);
        }
        if (uport->cons && uport->dev)
                of_console_check(uport->dev->of_node, uport->cons->name, uport->line);

        uart_configure_port(drv, state, uport);

        port->console = uart_console(uport);

        num_groups = 2;
        if (uport->attr_group)
                num_groups++;

        uport->tty_groups = kcalloc(num_groups, sizeof(*uport->tty_groups),
                                    GFP_KERNEL);
        if (!uport->tty_groups) {
                ret = -ENOMEM;
                goto out;
        }
        uport->tty_groups[0] = &tty_dev_attr_group;
        if (uport->attr_group)
                uport->tty_groups[1] = uport->attr_group;

        /*
         * Register the port whether it's detected or not.  This allows
         * setserial to be used to alter this port's parameters.
         */
        tty_dev = tty_port_register_device_attr_serdev(port, drv->tty_driver,
                        uport->line, uport->dev, port, uport->tty_groups);
        if (!IS_ERR(tty_dev)) {
                device_set_wakeup_capable(tty_dev, 1);
        } else {
                dev_err(uport->dev, "Cannot register tty device on line %d\n",
                       uport->line);
        }

        /*
         * Ensure UPF_DEAD is not set.
         */
        uport->flags &= ~UPF_DEAD;

 out:
        mutex_unlock(&port->mutex);
        mutex_unlock(&port_mutex);

        return ret;
}

这个函有两个参数:

  • drv:为哪个uart_driver 赋予一个uart_port;
  • uport:具体的 uart port;

一个 uart_port 代表了一个UART物理硬件,有多个UART的话,就要调用多次这个接口!

还记得之前那个uart_state结构么,它里面不就有一个 uart_port 么,没错,这里就是把这个uport 赋值给对应的这个state的uart_port成员。那么这个uart_port 又是从何而来的呢?既然是和芯片直接相关的,那么肯定是芯片厂家定义的。

具体函数执行流程如下:

参考文章

[1]S3C2440 Linux UART 串口驱动-----1

[2]Linux UART 驱动 Part-1 (底层对接)

[3]Linux UART 驱动 Part-2 (tty 层流程)

[4]Linux串口驱动分析及移植

[5]Linux系统TTY串口驱动实例详解

标签:tty,struct,UART,driver,uart,state,linux,驱动,port
From: https://www.cnblogs.com/zyly/p/17185739.html

相关文章

  • Linux 系统常见 的命令
    uname-a查看linux的版本信息;pwd:打印当前的工作目录,printworkdirectory;cd 改变目录,changedirectory;  cd.当前目录cd..上一级目录cd-返回之前的目......
  • 配置 kali linux 的 apt (包管理工具) ,换成国内源
    1.查看apt的源 输入命令:vim/etc/apt/sources.list   修改之后:快捷键A进入编辑模式;  ESC键然后输入" :wq " 就能退出vim编辑器;在输入......
  • linux下vim的使用以及高效率的技巧
    今天来介绍以下linux下vim的使用以及高效率的技巧目录一.关于vim编辑器二.vim编辑器的模式三.一般模式下的基础操作四.V模式(列模式)的基础操作五.命令模式下......
  • Rocky Linux 系列3 --- KVM
    一、概要1.环境RockyLinux9.12.KVMKVM是Kernel-basedVirtualMachine的简称,这是一个开源的针对Linux内核的虚拟化解决方案。它同时支持Intel和AMD的CPUs并且允许......
  • Linux下nano编辑器使用教程
    使用LinuxVPS会经常和编辑器打交道,一般常用的是vi和nano,虽然vi功能强大,但是相对新手来要稍微难上手,GNUnano是一个体积小巧而功能强大的文本编辑器。这里就简单说一下nan......
  • 每天一个linux命令 -- 系列教程
    Linux学习笔记Linux应用总结(1):自动删除n天前日志每天一个linux命令(61):wget命令每天一个linux命令(60):scp命令每天一个linux命令(59):rcp命令每天一个linux命令......
  • linux虚拟机连接不上putty
    1.linux虚拟机没有安装ssh2.虚拟机网卡模式设置错误3.防火墙未关闭查看防火墙状态有两种方式:执行命令firewall-cmd--state运行中running未启用notr......
  • FPGA 学习笔记:Vivado 2018.2 MicroBlaze Uartlite 配置
    前言Vivado版本:Vivado2018.2+VivadoHLS2018.2,VivadoHLS2018.2用于SDK开发,C语言开发创建基于MicroBlaze的【BlockDesign】后,添加了【AXIUartlite】,发现烧写......
  • Linux学习记录(五):环境变量
    Linux系统修改环境变量PATH一般将bin文件夹添加至PATH中,比如ffmpeg/conda等LD_LIBRARY_PATH可执行文件运行时链接库路径只在当前终端有效,终端export(对某一用户)......
  • linux下vim的使用以及高效率的技巧
    介绍以下linux下vim的使用以及高效率的技巧目录一.关于vim编辑器二.vim编辑器的模式三.一般模式下的基础操作四.V模式(列模式)的基础操作五.命令模式下的基础操作六.......