linux下用户程序同内核通信详解(netlink机制)

简介

linux下用户程序同内核通信的方式一般有ioctl, proc文件系统,剩下一个就是Netlink套接字了。 这里先介绍下netlink。

Netlink 是一种在内核与用户应用间进行双向数据传输的非常好的方式,用户态应用使用标准的 socket API 就可以使用 netlink 提供的强大功能,内核态需要使用专门的内核 API 来使用 netlink。

Netlink 相对于系统调用,ioctl 以及 /proc 文件系统而言具有以下优点:

1,为了使用 netlink,用户仅需要在 include/linux/netlink.h 中增加一个新类型的 netlink 协议定义即可, 如 #define NETLINK_MYTEST 17 然后,内核和用户态应用就可以立即通过 socket API 使用该 netlink 协议类型进行数据交换。但系统调用需要增加新的系统调用,ioctl 则需要增加设备或文件, 那需要不少代码,proc 文件系统则需要在 /proc 下添加新的文件或目录,那将使本来就混乱的 /proc 更加混乱。

2. netlink是一种异步通信机制,在内核与用户态应用之间传递的消息保存在socket缓存队列中,发送消息只是把消息保存在接收者的socket的接 收队列,而不需要等待接收者收到消息,但系统调用与 ioctl 则是同步通信机制,如果传递的数据太长,将影响调度粒度。

3.使用 netlink 的内核部分可以采用模块的方式实现,使用 netlink 的应用部分和内核部分没有编译时依赖,但系统调用就有依赖,而且新的系统调用的实现必须静态地连接到内核中,它无法在模块中实现,使用新系统调用的应用在编译时需要依赖内核。

4.netlink 支持多播,内核模块或应用可以把消息多播给一个netlink组,属于该neilink 组的任何内核模块或应用都能接收到该消息,内核事件向用户态的通知机制就使用了这一特性,任何对内核事件感兴趣的应用都能收到该子系统发送的内核事件,在 后面的文章中将介绍这一机制的使用。

5.内核可以使用 netlink 首先发起会话,但系统调用和 ioctl 只能由用户应用发起调用。

6.netlink 使用标准的 socket API,因此很容易使用,但系统调用和 ioctl则需要专门的培训才能使用。

下面这两部分代码主要的目的是用netlink机制实现用户程序和内核的通信。 具体就是用户程序执行./netlink -S [我是参数] 或./netlink -G 时,内核会返回"S know you!" 和“I know you!” 这两种字符串, 然后输出。 内核和用户程序均加有打印。

内核模块

1. Makefile依赖的编译规则 ruler.dir

PWD := $(shell pwd) 

all: modules romfs 

modules:
 $(MAKE) -C $(KDIR) M=$(PWD) modules
 @echo $(OBJ) 

modules_install:
 $(MAKE) -C $(KDIR) M=$(PWD) modules_install 

romfs:
 cp -rf *.ko $(MODULES_BUILD_DIR) 

clean:
 rm *.o *.ko *.mod.* Module.* modules.*
 rm -rf $(MODULES_BUILD_DIR) 

obj-m := $(MOD_NAME).o 

2.Makefile

KERNEL_MODULES := netlink 

export MODULES_ROOT_DIR := $(shell pwd)
export MODULES_BUILD_DIR := $(MODULES_ROOT_DIR)/build
export KDIR := /lib/modules/$(shell uname -r)/build #这行是为了取出系统下内核的目录(ubuntu) 

all: init modules romfs 

init:
 mkdir -p $(MODULES_BUILD_DIR) 

modules:$(patsubst %, _dir_%, $(KERNEL_MODULES)) 

$(patsubst %, _dir_%, $(KERNEL_MODULES)):
 @echo
 @echo Building $(patsubst _dir_%, %, $@)
 $(MAKE) -C $(patsubst _dir_%, %, $@) all 

romfs: $(patsubst %, _romfs_%, $(KERNEL_MODULES))
$(patsubst %, _romfs_%, $(KERNEL_MODULES)):
 $(MAKE) -C $(patsubst _romfs_%, %, $@) romfs 

clean: $(patsubst %, _clean_%, $(KERNEL_MODULES))
 $(RM) $(BUILD_DIR)
$(patsubst %, _clean_%, $(KERNEL_MODULES)):
 @echo
 @echo Cleaning $(patsubst _dir_%, %, $@)
 $(MAKE) -C $(patsubst _clean_%, %, $@) clean 

.PHONY: 

3. ./netlink/netlink.c

/*
 * netlink.c
 *
 * Created on: 2014 *  Author: cr
 */ 

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/netlink.h>
#include <net/sock.h>
#include "usrlink.h" 

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("MDAXIA"); 

struct sock *netlink_fd; 

static void netlink_to_user(int dest, void *buf, int len)
{
 struct nlmsghdr *nl;
 struct sk_buff *skb;
 int size; 

 size = NLMSG_SPACE(len);
 skb = alloc_skb(size, GFP_ATOMIC);
 if(!skb || !buf)
 {
  printk(KERN_ALERT "netlink_to_user skb of buf null!\n");
  return;
 }
 nl = nlmsg_put(skb, 0, 0, 0, NLMSG_SPACE(len) - sizeof(struct nlmsghdr), 0);
 NETLINK_CB(skb).pid = 0;
 NETLINK_CB(skb).dst_group = 0; 

 memcpy(NLMSG_DATA(nl), buf, len);
 nl->nlmsg_len = (len > 2) ? (len - 2):len; 

 netlink_unicast(netlink_fd, skb, dest, MSG_DONTWAIT);
 printk(KERN_ALERT "K send packet success\n");
} 

static int process_hello_get(int dest, void *buf, int len)
{
 printk(KERN_ALERT "In process_hello get!\n");
 memcpy(buf, "I known you !", 13);
 netlink_to_user(dest, buf, 13);
 return NET_OK;
} 

static int process_hello_set(int dest, void *buf, int len)
{
 printk(KERN_ALERT "In process_hello set! %s\n", (char *)buf);
 memcpy(buf, "S known you !", 13);
 netlink_to_user(dest, buf, 13);
 return NET_OK;
} 

static void netlink_process_packet(struct nlmsghdr *nl)
{
 int ret; 

 switch(nl->nlmsg_type)
 {
 case HELLO_GET:
  ret = process_hello_get(nl->nlmsg_pid, NLMSG_DATA(nl), nl->nlmsg_len);
  break;
 case HELLO_SET:
  ret = process_hello_set(nl->nlmsg_pid, NLMSG_DATA(nl), nl->nlmsg_len);
  break;
 default:break;
 }
} 

static void netlink_recv_packet(struct sk_buff *__skb)
{
 struct sk_buff *skb;
 struct nlmsghdr *nlhdr; 

 skb = skb_get(__skb);
 if(skb->len >= sizeof(struct nlmsghdr))
 {
  nlhdr = (struct nlmsghdr *)skb->data;
  if(nlhdr->nlmsg_len >= sizeof(struct nlmsghdr) &&
    __skb->len >= nlhdr->nlmsg_len)
  {
   netlink_process_packet(nlhdr);
  }
 }
 else
  printk(KERN_ALERT "Kernel receive msg length error!\n");
} 

static int __init netlink_init(void)
{
 netlink_fd = netlink_kernel_create(&init_net, USER_NETLINK_CMD, 0, netlink_recv_packet, NULL, THIS_MODULE);
 if(NULL == netlink_fd)
 {
  printk(KERN_ALERT "Init netlink!\n");
  return -1;
 }
 printk(KERN_ALERT "Init netlink success!\n");
 return 0;
} 

static void __exit netlink_exit(void)
{
 netlink_kernel_release(netlink_fd);
 printk(KERN_ALERT "Exit netlink!\n");
} 

module_init(netlink_init);
module_exit(netlink_exit); 

4. ./netlink/usrlink.h

/*
 * usrlink.h
 *
 * Created on: 2014骞?鏈?7鏃? *  Author: cr
 */
#ifndef USRLINK_H_
#define USRLINK_H_ 

#define USER_NETLINK_CMD 25
#define MAXMSGLEN   1024 

typedef enum error_e {
 NET_ERROR,
 NET_OK,
 NET_PARAM,
 NET_MEM,
 NET_SOCK,
} netlink_err; 

typedef enum module_e {
 HELLO_CMD = 1,
} netlink_module; 

typedef enum type_e {
 HELLO_SET,
 HELLO_GET,
} netlink_type; 

#endif /* USRLINK_H_ */ 

5. ./netlink/Makefile

MOD_NAME := netlink 

$(MOD_NAME)-objs : netlink.o 

-include $(MODULES_ROOT_DIR)/rules.dir 

.PHONY: 

6. 编译方式

其中Makefile、rulers.dir 在Knetlink/下, netlink.c 、netlink.h 、Makefile在Knetlink/netlink/目录下。 编译时在Knetlink目录下执行Make即可

用户程序

用户程序的Makefile 这里就不放出了。 我是直接在eclipse下建的工程 自动编译的、...

1. netlink.c

/*
 * usrlink.c
 *
 * Created on: 2014骞?鏈?7鏃? *  Author: cr
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "usrlink.h" 

int netlink_sock_init(netlink_sock *netlink_s, int module, int protocol)
{
 netlink_s->sock = socket(PF_NETLINK, SOCK_RAW, protocol);
 if(netlink_s->sock < 0)
  return NET_SOCK;
 memset(&netlink_s->src, 0 ,sizeof(netlink_s->src));
 netlink_s->src.nl_family = AF_NETLINK;
 netlink_s->src.nl_pid = module;
 netlink_s->src.nl_groups = 0; 

 if(bind(netlink_s->sock, (struct sockaddr *)&netlink_s->src, sizeof(netlink_s->src)) < 0)
  return NET_SOCK; 

 netlink_s->dest.nl_family = AF_NETLINK;
 netlink_s->dest.nl_pid = 0;
 netlink_s->dest.nl_groups = 0; 

 return NET_OK;
} 

int netlink_send(netlink_sock *netlink_s, int type, char *sbuf, int slen, char *rbuf, int *rlen)
{
 struct msghdr msg;
 struct nlmsghdr *nlhdr = NULL;
 struct iovec iov;
 int ret; 

 nlhdr = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAXMSGLEN));
 if(NULL == nlhdr)
  return NET_MEM; 

 memcpy(NLMSG_DATA(nlhdr), sbuf, slen);
 nlhdr->nlmsg_len = NLMSG_SPACE(slen);
 nlhdr->nlmsg_pid = netlink_s->src.nl_pid;
 nlhdr->nlmsg_type = type;
 nlhdr->nlmsg_flags = 0; 

 iov.iov_base = (void *)nlhdr;
 iov.iov_len = nlhdr->nlmsg_len; 

 msg.msg_name = (void *)&(netlink_s->dest);
 msg.msg_namelen = sizeof(netlink_s->dest);
 msg.msg_iov = &iov;
 msg.msg_iovlen = 1; 

 ret = sendmsg(netlink_s->sock, &msg, 0);
 if(ret < 0)
 {
  printf("Send fail\n");
  goto error;
 }
 ret = recvmsg(netlink_s->sock, &msg, 0);
 if(ret < 0)
 {
  printf("Read fail\n");
  goto error;
 }
 memcpy(rbuf, NLMSG_DATA(nlhdr), nlhdr->nlmsg_len);
 *rlen = nlhdr->nlmsg_len;
 return NET_OK; 

error:
 free(nlhdr);
 return NET_SOCK;
} 

int netlink_sock_deinit(netlink_sock *netlink_s)
{
 close(netlink_s->sock);
 memset(netlink_s, 0, sizeof(netlink_sock));
 return NET_OK;
} 

2. netlink.h

/*
 * usrlink.h
 *
 * Created on: 2014 *  Author: cr
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <asm/types.h>
#include <linux/socket.h>
#include <linux/netlink.h>
#ifndef USRLINK_H_
#define USRLINK_H_ 

#define USER_NETLINK_CMD 25
#define MAXMSGLEN   1024 

typedef enum error_e {
 NET_ERROR,
 NET_OK,
 NET_PARAM,
 NET_MEM,
 NET_SOCK,
} netlink_err; 

typedef enum module_e {
 HELLO_CMD = 1,
} netlink_module; 

typedef enum type_e {
 HELLO_SET,
 HELLO_GET,
} netlink_type; 

typedef struct usr_sock_h {
 int sock;
 struct sockaddr_nl dest;
 struct sockaddr_nl src;
} netlink_sock; 

int netlink_sock_init(netlink_sock *netlink_s, int module, int protocol);
int netlink_sock_deinit(netlink_sock *netlink_s);
int netlink_send(netlink_sock *netlink_s, int type, char *sbuf, int slen, char *rbuf, int *rlen); 

#endif /* USRLINK_H_ */ 

3. main.c

/*
 * main.c
 *
 * Created on: 2014骞?鏈?7鏃? *  Author: cr
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "usrlink.h" 

int parse_ret(int ret)
{
 switch(ret)
 {
 case NET_OK:
  return ret;
 case NET_ERROR:
  printf("error\n");
  goto exit_p;
 case NET_MEM:
  printf("Memory error\n");
  goto exit_p;
 case NET_PARAM:
  printf("Param error\n");
  goto exit_p;
 case NET_SOCK:
  printf("Socket error\n");
  goto exit_p;
 default:break;
 }
exit_p:
 return NET_ERROR;
} 

void usage(void)
{
 printf("Usage: Netlink -G <param>\n\t-S <param>\n");
} 

int main(int argc, char **argv)
{
 netlink_sock h_sock;
 char rbuf[1024];
 char sbuf[1024];
 int ret, type, slen = 0, rlen = 0; 

 ret = netlink_sock_init(&h_sock, HELLO_CMD, USER_NETLINK_CMD);
 if(NET_OK != parse_ret(ret))
  goto exit_p; 

 bzero(&rbuf, sizeof(rbuf));
 bzero(&sbuf, sizeof(sbuf));
 if(argc < 3)
 {
  usage();
  goto exit_p;
 }
 if(!strncmp("-G", argv[1], 2))
  type = HELLO_GET;
 else if(!strncmp("-S", argv[1], 2))
  type = HELLO_SET; 

 strcpy(sbuf, argv[2]);
 slen = strlen(sbuf);
 ret = netlink_send(&h_sock, type, sbuf, slen, rbuf, &rlen);
 if(NET_OK != parse_ret(ret))
  goto exit_p; 

 if(rlen > 0)
 {
  rbuf[rlen] = '\0';
  printf("K rep [len = %d]:%s\n", rlen, rbuf);
 }
 printf("K[len = %d]: %s\n", rlen, rbuf); 

exit_p:
 netlink_sock_deinit(&h_sock);
 return 0;
} 

总结

以上就是本文关于linux下用户程序同内核通信详解(netlink机制)的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

您可能感兴趣的文章:

  • Linux利用Sysctl命令调整内核参数
  • Linux内核参数调整方法
  • Linux 内核通用链表学习小结
  • Linux内核启动参数详解
  • 简单谈谈Linux内核定时器
  • Linux中的内核链表实例详解
  • 浅谈安装ORACLE时在Linux上设置内核参数的含义
  • Centos下编译Linux内核的具体实现方法
(0)

相关推荐

  • Linux中的内核链表实例详解

    Linux中的内核链表实例详解 链表中一般都要进行初始化.插入.删除.显示.释放链表,寻找节点这几个操作,下面我对这几个操作进行简单的介绍,因为我的能力不足,可能有些东西理解的不够深入,造成一定的错误,请各位博友指出. A.Linux内核链表中的几个主要函数(下面是内核中的源码拿出来给大家分析一下) 1)初始化: #define INIT_LIST_HEAD(ptr) do { \ (ptr)->next = (ptr); (ptr)->prev = (ptr); \ } while (0)

  • Linux利用Sysctl命令调整内核参数

    前言 sysctl 命令被用于在内核运行时动态地修改内核的运行参数,可用的内核参数在目录 /proc/sys 中.它包含一些TCP/IP堆栈和虚拟内存系统的高级选项, 这可以让有经验的管理员提高引人注目的系统性能.用sysctl可以读取设置超过五百个系统变量. 1.常见用法 列出所有的变量并查看 sysctl -a | less 修改某变量的值 sysctl -w 变量名=变量值 #sysctl -w vm.max_map_count=262144 读一个指定的变量,例如 kernel.msgm

  • 简单谈谈Linux内核定时器

    软件意义上的定时器最终依赖硬件定时器来实现, 内核在时钟中断发生后检测各定时器是否到期 , 到期后的定时器处理函数将作为软中断在底半部执行 .实质上,时钟中断处理程序会 换起TIMER_SOFTIRQ软中断 ,运行当前处理器上到期的所有定时器. 总结起来还是软中断的流程 a.注册软中断处理函数 /*/linux/kernel.timer.c*/ void __init init_timers(void) -->open_softirq(TIMER_SOFTIRQ, run_timer_softi

  • Centos下编译Linux内核的具体实现方法

    Linux内核编译是一件简单却费事的事.但是独立的编译linux内核会帮助你很好的理解Linux内核的工作机理. 首先编译linux内核我们需要在当前linux操作系统下安装gcc编译器,因为我是Centos distribution版本 yum install gcc 接下来安装依赖环境: yum install ncurses-devel 现在我们以linux-3.18.1内核为例进行编译,假设我当前系统的版本为2.6.32 那么我首先在Linux内核发布的官网上http:/kernel.o

  • Linux内核参数调整方法

    ulimit设置 ulimit -n 要调整为100000甚至更大. 命令行下执行 ulimit -n 100000即可修改.如果不能修改,需要设置 /etc/security/limits.conf,加入 * soft nofile 262140 * hard nofile 262140 root soft nofile 262140 root hard nofile 262140 * soft core unlimited * hard core unlimited root soft co

  • Linux 内核通用链表学习小结

    描述 在linux内核中封装了一个通用的双向链表库,这个通用的链表库有很好的扩展性和封装性,它给我们提供了一个固定的指针域结构体,我们在使用的时候,只需要在我们定义的数据域结构体中包含这个指针域结构体就可以了,具体的实现.链接并不需要我们关心,只要调用提供给我们的相关接口就可以完成了. 传统的链表结构 struct node{ int key; int val; node* prev; node* next; } linux 内核通用链表库结构 提供给我们的指针域结构体: struct list

  • Linux内核启动参数详解

    1.环境: Ubuntu 16.04 Linux linuxidc 4.4.0-89-generic #112-Ubuntu SMP Mon Jul 31 19:38:41 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux 2.查看当前linux内核的启动参数: cat /proc/cmdline 笔者的输出内容如下: BOOT_IMAGE=/boot/vmlinuz-4.4.0-89-generic root=UUID=bef418fa-4202-4513-b39

  • 浅谈安装ORACLE时在Linux上设置内核参数的含义

    前两天看到一篇Redhat官方的Oracle安装文档,对于Linux内核参数的修改描述的非常清晰. 安装Oracle之前,除了检查操作系统的硬件和软件是否满足安装需要之外,一个重点就是修改内核参数,其中最主要的是和内存相关的参数设置. SHMMAX参数:Linux进程可以分配的单独共享内存段的最大值.一般设置为内存总大小的一半.这个值的设置应该大于SGA_MAX_TARGET或MEMORY_MAX_TARGET的值,因此对于安装Oracle数据库的系统,shmmax的值应该比内存的二分之一大一些

  • linux下用户程序同内核通信详解(netlink机制)

    简介 linux下用户程序同内核通信的方式一般有ioctl, proc文件系统,剩下一个就是Netlink套接字了. 这里先介绍下netlink. Netlink 是一种在内核与用户应用间进行双向数据传输的非常好的方式,用户态应用使用标准的 socket API 就可以使用 netlink 提供的强大功能,内核态需要使用专门的内核 API 来使用 netlink. Netlink 相对于系统调用,ioctl 以及 /proc 文件系统而言具有以下优点: 1,为了使用 netlink,用户仅需要在

  • Linux 下读XML 的类详解及实现代码

     Linux 下读XML 的类详解及实现代码 在Linux下写程序,常需要读一些配置文件.现有的XML工具很多,可以方便的编辑和生成XML. 但VC中用的XML解析器在Linux下不能用.只好自已写了个.用了一下,还不错. #include <stdio.h> #include <stdlib.h> // ********************************************************************** // // XML解析类(hongh

  • linux下安装solr的教程详解

    安装Solr 第一步:将solr的压缩包上传到Linux系统 第二步:解压tomcat tar -zvxf apache-tomcat-7.0.47.tar.gz [root@localhost ~]# tar -zxvf apache-tomcat-7.0.47.tar.gz 第三步:在/usr/local/新建目录solr 第四步:将tomcat拷贝在/usr/local/solr/目录下,并命名为tomcat 第五步 解压solr [root@localhost ~]# tar -zvxf

  • Linux下的fdisk命令用法详解

    Linux下的fdisk功能是极其强大的,用它可以划分出最复杂的分区,下面简要介绍一下它的用法: 对于IDE硬盘,每块盘有一个设备名:对应于主板的四个IDE接口,设备名依次为:/dev/hda,/dev/hdb,/dev/hdc,/dev/hdd等, 如果还有IDE Raid卡,则依次为:/dev/hde,/dev/hdf,/dev/hdg,/dev/hdh.对于SCSI硬盘,则设备名依次为/dev/sda,/dev/sdb...等等 fdisk的命令行用法为: fdisk 硬盘设备名 进入fd

  • Linux下安装mysql的教程详解

    1. 关闭mysql服务 # service mysqld stop 2. 检查是否有rpm包,如果没有用rpm安装过mysql,不应该有残留,如果有,需要删掉 检查语法: rpm -qa|grep -i mysql 删除语法: rpm -e <包的名字> 如果遇到依赖,无法删除,使用 rpm -e --nodeps <包的名字> 不检查依赖,直接删除rpm包. 3. 通过find命令检查是否有安装mysql文件,有需要删除 检查语法: find / -name mysql 删除语

  • 如何测试Linux下tcp最大连接数限制详解

    前言 关于TCP服务器最大并发连接数有一种误解就是"因为端口号上限为65535,所以TCP服务器理论上的可承载的最大并发连接数也是65535". 先说结论:对于TCP服务端进程来说,他可以同时连接的客户端数量并不受限于可用端口号.并发连接数受限于linux可打开文件数,这个数是可以配置的,可以非常大,所以实际上受限于系统性能. 现在做服务器开发不加上高并发根本没脸出门,所以为了以后吹水被别人怼"天天提高并发,你自己实现的最高并发是多少"的时候能义正言辞的怼回去,趁着

  • Linux下重新启动Tomcat的步骤详解

    本文主要介绍的是Linux下重新启动Tomcat的步骤,在Linux系统下,重启Tomcat使用命令操作的! 具体的步骤如下: 首先,进入Tomcat下的bin目录 cd /usr/local/tomcat/bin 使用Tomcat关闭命令 ./shutdown.sh 查看Tomcat是否以关闭 ps -ef|grep java 如果显示以下相似信息,说明Tomcat还没有关闭 root 7010 1 0 Apr19 ? 00:30:13 /usr/local/java/bin/java -Dj

  • linux下配置yum源方法详解

    本人使用的方法一,成功配置,方法二没测过,可以作为参考 方法一: 1.确保RHEL5中已经安装了yum [root@lvs-master ~]# rpm -qa |grep yum yum-metadata-parser-2-el5 yum-updatesd-9-el5 yum-22-el5 yum-security-16-el5 yum-rhn-plugin-4-el5 2.修改源配置文件 #vim /etc/yum.repos.d/CentOS-Base.repo (如果目录下没有.repo

  • linux下python中文乱码解决方案详解

    1. 场景描述 linux服务器下安装了Anaconda3,执行Pyhton的K-means算法,结果出现如下图的中文字符乱码.上次已经解决了,忘记记录解决流程了,这次配置了一台新的服务器,又出现,默认不配置的话matplotlib画图就会乱码,这次把解决过程记录下,希望能帮助自己和有需要的朋友. 2. 解决方案 网上有好几个解决方案,只介绍自己实战可行的. 1. 查看matplotlib字体位置 python import matplotlib print(matplotlib.matplot

  • Linux下alias命令的用法详解

    1.alias的使用 alias命令用来设置指令的别名.我们可以使用该命令可以将一些较长的命令进行简化. 用alias 短命令='原命令 选项' alias 138ssh= 'ssh -i ~/.ssh/138.pem ec2-user@192.168.21.138' 这下子就可以直接使用138ssh 来代替原来ssh -i ~/.ssh/138.pem ec2-user@192.168.21.138 查看当前所有的alias alias-p 删除一个alias unalias 命令 然后我就开

随机推荐