Linux终端简介

news2024/12/26 9:55:03

Linux终端简介

  • 导语
  • 基本终端交互
    • 终端读写
      • 标准/非标准模式
      • 重定向处理
    • 终端对话
  • termios结构
    • 模式相关
      • 输入模式
      • 输出模式
      • 控制模式
      • 本地模式
      • 特殊控制字符
      • 终端速度
      • 其他函数
  • 终端输出
    • 终端类型
    • terminfo
  • 击键动作检测
  • 虚拟控制台&伪终端
  • 总结
  • 参考文献

导语

本章基本是以一个简单的用户交互程序作为基准,随后逐步拓宽,最后完成一个功能较为齐全的C语言交互程序,涉及到的知识点有输入输出模式、termios结构等

基本终端交互

终端读写

书上给出了一个简单的菜单例子,具体代码和运行结果如下

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <pwd.h>
#include <syslog.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <math.h>
#include <time.h>
char *menu[]=
{
    "a - add new record",
    "d - delete record",
    "q - quit",
    NULL,
};

int getchoice(char *greet, char *choices)//实现选择
{
    int choose=0,selected;
    char **option;
    do
    {
        printf("Choice: %s\n",greet);
        option=choices;
        while(*option)
        {
            printf("%s\n",*option);
            option++;
        }
        selected=getchar();//尝试获得输入
        option=choices;
        while(*option)
        {
            if(selected==*option[0])
            {
                choose=1;
                break;
            }
            option++;
        }
        if(!choose)
            printf("Incorrect choice, select again\n");
    }while(!choose);
    return selected;
}
int main()
{
    int choice=0;
    do
    {
        choice=getchoice("Please select an action",menu);//获取选项
        printf("You have chosen: %c\n",choice);
    }while(choice!='q');
    return 0;
}

结果如下,可以发现,每次似乎多运行了一次getchoice函数,导致有一次无效的输出,这其实是因为输入实际上处理的是两个字符,一个是输入的字母,另一个是回车

在这里插入图片描述

标准/非标准模式

像上面所述的,只有在用户按下回车时,程序才能读到用户的输入,这种模式叫标准模式,它允许用户在真正要输入给程序时对输入进行修改,与标准模式相对的事非标准模式,它有更大的控制权

并且,在上述程序中,用户输入的是回车,但是程序看到的字符并不是回车符CR,而是换行符LF,因为Linux以换行符作为文本行的结束,一些操作系统用回车符和换行符两个字符的结合来表示一行的结束

可以将上述程序的字符获取部分改成

while((selected=getchar())=='\n');

这样就能把换行符给去掉了

重定向处理

Linux中可以将程序的I/O重定向到其他文件或程序,例如将刚才的程序进行重定向,得到的结果如下

在这里插入图片描述

可以看到程序的输出被重定向到文件,而不是显示终端,有时甚至可以让用户看到的提示信息与其他输出进行区分对待,比如一个被输出到终端,另一个被重定向,例如,当stdout已经被重定向的时候,可以使用stderr输出信息

可以通过检查底层文件描述符与终端的关联关系来进行判断,系统调用isatty就是用来完成这一任务的,函数原型如下

int isatty(int fd);
//fd存在与终端的链接,返1,否则0

在主函数添加了对文件描述符的判断之后,运行程序的结果如下,可以看到,当进行重定向的时候,信息通过stderr输出到了终端

在这里插入图片描述

终端对话

上述程序有一个问题,程序的所有输出全部都重定向到文件当中了,但有时我们希望程序的交互部分不被重定向,其他的IO可以被重定向,这个时候就需要将交互部分与标准流分开,Linux提供了解决方案——对终端进行读写,Linux本身是多用户系统,通常有多个终端

Linux提供了一个特殊目录/dev/tty实现对终端的读写,该目录始终指向当前终端或登录对话

书上给出了使用/dev/tty的实现

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <pwd.h>
#include <syslog.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <math.h>
#include <time.h>
char *menu[]=
{
    "a - add new record",
    "d - delete record",
    "q - quit",
    NULL,
};

int getchoice(char *greet, char *choices[],FILE*in,FILE*out)//实现选择
{
    int choose=0,selected;

    char **option;
    do
    {
        fprintf(out,"Choice: %s\n",greet);
        option=choices;
        while(*option)
        {
            fprintf(out,"%s\n",*option);//这里被修改,输出的对象为终端
            option++;
        }
        while((selected=fgetc(in))=='\n');//输入的对象也是终端
        option=choices;
        while(*option)
        {
            if(selected==*option[0])
            {
                choose=1;
                break;
            }
            option++;
        }
        if(!choose)
            fprintf(out,"Incorrect choice, select again\n");
    }while(!choose);
    return selected;
}
int main()
{
    int choice=0;
     FILE* input,*output;
     input=fopen("/dev/tty","r");//打开终端
     output=fopen("/dev/tty","w");//写入终端
     if(!input||!output)
     {
         fprintf(stderr,"无法打开制定目录\n");
         exit(1);
     }
    if(!isatty(fileno(stdout)))
    {
        fprintf(stderr,"非终端输出\n");
        //exit(1);
    }
    do
    {
        choice=getchoice("Please select an action",menu,input,output);//获取选项
        printf("You have chosen: %c\n",choice);
    }while(choice!='q');
    return 0;
}

运行的结果如下,可以看到交互部分和程序的输出部分分别输出到不同的地方

在这里插入图片描述

termios结构

termios是POSIX定义的标准接口,可以通过设置它的成员变量以及使用函数调用来完成对终端接口的控制

termios可以调整的值有I/O模式,本地模式和特殊控制字符,最小的termios结构定义如下

#include <termios.h>  
  
struct termios {  
    tcflag_t c_iflag;   // 输入模式标志  
    tcflag_t c_oflag;   // 输出模式标志  
    tcflag_t c_cflag;   // 控制模式标志  
    tcflag_t c_lflag;   // 本地模式标志  
    cc_t c_cc[NCCS];    // 控制字符数组  
    // 可能还有其他成员,如c_ispeed和c_ospeed(在某些实现中)  
};

可以使用tcgetattr初始化一个terimos结构,函数原型如下

int tcsetattr(int fd,int actions,const struct termios *termios_p);

actions有三种取值,TCSANOW(立刻对值修改),TCSADRAIN(当前输出完再对值进行修改),TCSAFLUSH(当前的输出完成后再对值进行修改,丢弃还未从read调用返回的当前可用的任何输入)

模式相关

通过设置termios对应的成员变量的值,可以实现对终端各种模式的控制

输入模式

输入模式控制输入数据(终端驱动程序从串行口或键盘接受到的字符)在被传递给程序前的处理方式,通过设置c_iflag的宏可以设置输入模式,通常用户无需修改,默认值就是最合适的,设置的时候可以用OR来一次性设置多个约束,c_iflag用到的宏具体可以见手册

输出模式

输出模式控制输出字符的处理方式,即程序发送出去的字符在传递到串行口或屏幕前是如何处理的,很多处理方式正好与输入模式是对应的,可以通过设置c_oflag成员对输出模式进行控制,一用到的宏具体可以见手册

控制模式

控制模式控制终端的硬件特性,可以通过设置c_cflag进行配置,用到的宏具体可以见手册

本地模式

本地模式控制终端的各种特性,可以设置c_lflag来实现对本地模式的配置,用到的宏具体可以见手册

特殊控制字符

特殊控制字符是字符组合,当用户输入对应的组合键,终端会有一些特殊的处理方式,c_cc数组成员将各种特殊控制字符映射到对应的支持函数(可以联想计组的终端处理),每个字符的位置由一个宏定义,并且在不同模式下(标准和非标准)数组下标有重叠部分,标准模式和非标准模式下使用的数组下标具体可以见手册

除了这些支持函数外,还有一对重要的非标准模式下的参数TIME和MIN,通过设置它们,可以使得程序逐个字符地处理,他们结合的情况一般是四种情况,(0,0)、(>0,0)、(>0,>0)、(0,>0),具体含义见书或手册

还可以通过stty命令查看termios的取值

在这里插入图片描述

终端速度

termios还可以控制I/O速度,只需要调用对应的函数即可,需要注意的是输入和输出速度并不是同时设置的,函数原型如下

speed_t cfgetispeed(const struct termios*);
speed_t cfgetospeed(const struct termios*);
int cfsetispeed(struct termios*,speed_t speed);
int cfsetospeed(struct termios*,speed_t speed);

显而易见,这四个函数都是存取器,speed的值有很多,如B0,B1200,B9600等,此处不赘述

其他函数

还有一些其他的函数,直接对文件描述符进行操作,不需要经过termios,函数原型如下

int tcdrain(int fd);
//让调用程序移植等待,直到所有排队输出完
int tcflow(int fd,int flowtype);
//暂停或重新开始输出
int tcflush(int fd,int in_out_selector);
//清空输入或输出

书上给出了一个简单取消密码回显的程序,代码如下

#include <termios.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    struct termios initset,newset;
    char password[8];
    tcgetattr(fileno(stdin),&initset);
    newset=initset;
    newset.c_lflag&=~ECHO;//这里取消了密码回显
    printf("输入密码:");
    if(tcsetattr(fileno(stdin),TCSAFLUSH,&newset)!=0)//使用TCSAFLUSH丢弃用户在
    //程序准备好前的输入
        fprintf(stderr,"设置错误");
    else
    {
        fgets(password,8,stdin);
        tcsetattr(fileno(stdin),TCSANOW,&initset);//初始化设置
        fprintf(stdout,"\n输入的密码为%s\n",password);
    }
    return 0;
}

运行的结果如下,可以看到密码在输入的时候成功没有回显

在这里插入图片描述

在上述基础上,可以对menu进行进一步的修改,使得用户一输入程序就执行,并且不产生用户的回显,书上给出的修改后的程序和结果如下

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <pwd.h>
#include <syslog.h>
#include <termios.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <math.h>
#include <time.h>
char *menu[]=
{
    "a - add new record",
    "d - delete record",
    "q - quit",
    NULL,
};

int getchoice(char *greet, char *choices[],FILE*in,FILE*out)//实现选择
{
    int choose=0,selected;

    char **option;
    do
    {
        fprintf(out,"Choice: %s\n",greet);
        option=choices;
        while(*option)
        {
            fprintf(out,"%s\n",*option);
            option++;
        }
        while((selected=fgetc(in))=='\n'||selected=='\r');
        //非标准模式,回车和换行之间的映射不存在,需要对回车单独判断
        option=choices;
        while(*option)
        {
            if(selected==*option[0])
            {
                choose=1;
                break;
            }
            option++;
        }
        if(!choose)
            fprintf(out,"Incorrect choice, select again\n");
    }while(!choose);
    return selected;
}
int main()
{
    int choice=0;
     FILE* input,*output;
     input=fopen("/dev/tty","r");//打开终端
     output=fopen("/dev/tty","w");//写入终端
     struct termios initset,newset;//termios变量,用来实现设置
     if(!input||!output)
     {
         fprintf(stderr,"无法打开制定目录\n");
         exit(1);
     }
    if(!isatty(fileno(stdout)))
    {
        fprintf(stderr,"非终端输出\n");
        //exit(1);
    }
    tcgetattr(fileno(input),&initset);
    newset=initset;
    newset.c_lflag&=~ICANON;
    newset.c_lflag&=~ECHO;
    newset.c_cc[VMIN]=1;
    newset.c_cc[VTIME]=0;
    //设置MIN和TIME,有min个字符读取就返回
    newset.c_lflag&=~ISIG;
    if(tcsetattr(fileno(input),TCSANOW,&newset)!=0)
        fprintf(stderr,"设置错误\n");
    do
    {
        choice=getchoice("Please select an action",menu,input,output);//获取选项
        printf("You have chosen: %c\n",choice);
    }while(choice!='q');
    tcsetattr(fileno(input),TCSANOW,&initset);
    return 0;
}

在这里插入图片描述

终端输出

通过termios结构可以控制键盘的输入,有时用户会要求对程序输出到屏幕上的内容也有同样的控制能力(例如输出到屏幕的特定位置)

终端类型

终端是系统和用户交互的界面,在Linux中,通常使用terminfo软件包来和终端交互,有时候还需要用到curses

可以通过查询TERM变量来查看系统用的是什么样的终端

在这里插入图片描述

每个终端都有一个定义其功能标志和如何访问其特征的文件的文件,真正的文件都保存在下一级的子目录中,子目录名就是终端类型名的第一个字母

terminfo

每个终端类型都对应一个terminfo文件,terminfo定义由三种类型的数据项组成,分别对应终端的一种功能标志,分别是布尔功能标志、数值功能标志、字符串功能标志

在这里插入图片描述

大多数系统已经预定好了大部分终端的功能标志,还有修改escape转移序列,这里不赘述

使用terminfo时要调用setupterm设置终端类型,这将为当前终端类型初始化为一个TERMINAL结构,函数原型如下

int setupterm(char *term, int fd,int*errret);
//当前终端类型设置为term指向的值(空默认是TERM),fd是打开的文件描述符
//errret保存返回的函数值,-1数据库不存在,0无匹配,1,成功

在成功设置term之后,可以通过功能标志访问器来访问terminfo的功能标志,函数原型如下

int tigetflag(char *capname);
int tigetnum(char *capname);
char *tigetstr(char *capname);

下面是书上一个显示终端显示区大小的程序代码和运行结果

#include <stdio.h>
#include <term.h>
#include <curses.h>
#include <stdlib.h>
int main()
{
    int row,col;
    setupterm(NULL,fileno(stdout),(int*)0);
    row=tigetnum("lines");
    col=tigetnum("cols");
    printf("大小为%d * %d\n",row,col);
    exit(0);
}

需要注意的是执行的时候可能会遇到term.h无法找到的问题,这里可以参考另一篇(Ubuntu23.10下处理libncurses5-dev包的安装问题),以及编译时要加上-lcurses与对应的库进行链接,可以看到输出了终端的界面大小

在这里插入图片描述

除此之外,还可以用tparm函数用实际数值替换功能标志中的参数,用tparm构造好终端的escape转移序列后,必须将序列发送到终端,并且必须用putp或者tputs来处理终端完成一个操作所需要的延时,相关函数原型如下

char *tparm(char *cap,long p1,long p2,...,long p9);
int putp(char *const str);//以一个终端字符串为函数,将其发送到stdout
int tputs(char *const str, int affcnt, int (*putfunc)(int));
//为不能通过stdout访问终端的情况准备的,可以指定一个用于输出字符的函数
//返回值是用户指定函数的返回结果,affcnt是受这一变化影响的函数
//putp(str)等价于tputs(str,1,putchar)

使用上述函数完成最终菜单程序和运行结果如下,需要注意的是,下面这个程序继承的是先前的termios,也就是说不会对用户的输入进行回显

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <pwd.h>
#include <syslog.h>
#include <termios.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <math.h>
#include <time.h>
#include <term.h>
#include <curses.h>
static FILE *output_stream;
char *menu[]=
{
    "a - add new record",
    "d - delete record",
    "q - quit",
    NULL,
};

int char_to_terminal(int flag)
{
    if(output_stream)putc(flag,output_stream);//把flag的值送给输出流
    return 0;
}

int getchoice(char *greet, char *choices[],FILE*in,FILE*out)//实现选择
{
    int choose=0,selected;
    int row=4,col=10;
    char *cursor,*clear;
    char **option;
    option=choices;
    output_stream=out;
    setupterm(0,fileno(out),0);//设置term类型
    cursor=tigetstr("cup");//拿终端的值
    clear=tigetstr("clear");//同上
    tputs(clear,1,char_to_terminal);//清屏
    tputs(tparm(cursor,row,col),1,char_to_terminal);//设置光标到指定位置
    fprintf(out,"Choice: %s\n",greet);
    row+=2;
    while(*option)
    {
        tputs(tparm(cursor,row,col),1,char_to_terminal);
        fprintf(out,"%s\n",*option);
        row++;
        option++;
    }
    fprintf(out,"\n");
    do
    {
        fflush(out);
        while((selected=fgetc(in))=='\n'||selected=='\r');
        //非标准模式,回车和换行之间的映射不存在,需要对回车单独判断
        option=choices;
        while(*option)
        {
            if(selected==*option[0])
            {
                choose=1;
                break;
            }
            option++;
        }
        if(!choose)
        {
            tputs(tparm(cursor,row,col),1,char_to_terminal);
            fprintf(out,"Incorrect choice, select again\n");
        }
    }
    while(!choose);
    tputs(clear,1,char_to_terminal);
    return selected;
}
int main()
{
    int choice=0;
    FILE* input,*output;
    input=fopen("/dev/tty","r");//打开终端
    output=fopen("/dev/tty","w");//写入终端
    struct termios initset,newset;//termios变量,用来实现设置
    if(!input||!output)
    {
        fprintf(stderr,"无法打开制定目录\n");
        exit(1);
    }
    if(!isatty(fileno(stdout)))
    {
        fprintf(stderr,"非终端输出\n");
        //exit(1);
    }
    tcgetattr(fileno(input),&initset);
    newset=initset;
    newset.c_lflag&=~ICANON;
    newset.c_lflag&=~ECHO;
    newset.c_cc[VMIN]=1;
    newset.c_cc[VTIME]=0;
    //设置MIN和TIME,有min个字符读取就返回
    newset.c_lflag&=~ISIG;
    if(tcsetattr(fileno(input),TCSANOW,&newset)!=0)
        fprintf(stderr,"设置错误\n");
    do
    {
        choice=getchoice("Please select an action",menu,input,output);//获取选项
        printf("You have chosen: %c\n",choice);
        sleep(10);//睡10s后刷屏
    }
    while(choice!='q');
    tcsetattr(fileno(input),TCSANOW,&initset);
    return 0;
}

在这里插入图片描述

击键动作检测

Linux中没有MS-DOS对应的kbhit函数,但是可以通过termios等实现,下面给出书上的代码和运行结果

程序将终端设置为有字符读取时read才返回,kbnit将终端改成检查输入并立刻返回,在程序退出前回复终端的初始设置

#include <stdio.h>
#include <stdlib.h>
#include <term.h>
#include <curses.h>
#include <unistd.h>
struct termios initset,newset;
int peek=-1;
void init_keyboard()
{
    tcgetattr(0,&initset);//拿初始设置用来还原
    newset=initset;
    newset.c_lflag&=~ICANON;
    newset.c_lflag&=~ECHO;//取消回显
    newset.c_lflag&=~ISIG;
    newset.c_cc[VMIN]=1;
    newset.c_cc[VTIME]=0;
    //read一直等待,直到有1个字符才返回
    tcsetattr(0,TCSANOW,&newset);
    //设置termios
}
void close_keyboard()
{
    tcsetattr(0,TCSANOW,&initset);//还原设置
}
int kbhit()
{
    char ch;
    int nread;
    if(peek!=-1)return 1;//如果没输入
    newset.c_cc[VMIN]=0;
    tcsetattr(0,TCSANOW,&newset);
    nread=read(0,&ch,1);
    newset.c_cc[VMIN]=1;
    tcsetattr(0,TCSANOW,&newset);
    if(nread==1)
    {
        peek=ch;
        return 1;
    }
    return 0;
}
int readch()
{
    char ch;
    if(peek!=-1)
    {
        ch=peek;
        peek=-1;
        return ch;
    }
    read(0,&ch,1);
}
int main()
{
    int ch=0;
    init_keyboard();
    while(ch!='q')
    {
        printf("循环\n");
        sleep(1);
        if(kbhit())
        {
            ch=readch();
            printf("你按下了%c\n",ch);
        }
    }
    close_keyboard();
    return 0;
}

在这里插入图片描述

虚拟控制台&伪终端

linux提供了虚拟控制台,多个虚拟控制台可以提供给用户使用并切换,虚拟控制台通过/dev/ttyN使用(N为数字),使用who和ps可以看到进入系统的用户以及在当前虚拟控制台上运行的shell和程序

在这里插入图片描述

伪终端和一般的终端相似,区别是伪终端没有对应的硬件设备,类似于给其他程序提供终端形式的接口,过去伪终端以特定方式实现,但现在已经被合并到UNIX规范里,一般叫UNIX98/PTY(2010年)

总结

本章的内容很多,Linux对终端的操作繁多,并且有专门的结构体供操作,除此之外,各种其他的流也可以操作,比如stdout和dev等

参考文献

  1. 《Linux程序设计(第四版)》
  2. Ubuntu23.10下处理libncurses5-dev包的安装问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2167641.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PlayerPerfs-不同平台的存储位置

一 .PlayerPrefs存储的数据存在哪里 不同平台存储位置不一样 Windows PlayerPrefs 存储在 HKCU\Software\[公司名称]\[产品名称] 项下的注册表中 其中公司和产品名称是 在“Project Settings”中设置的名称。 查看方法&#xff1a; 运行 regedit HKEY…

手游和应用出海资讯:三七新游首月收入突破700万元;领英尝试推出游戏功能以增加用户使用时长

NetMarvel帮助游戏和应用广告主洞察全球市场、获取行业信息&#xff0c;以下为9月第四周资讯&#xff1a; ● 《AFK Journey》收入突破 1.5 亿美元 ● 《黑神话&#xff1a;悟空》IGN年度游戏投票第一掉至第三 ● 三七发布新游首月收入突破700万元 ● 开罗游戏《哆啦A梦的铜锣烧…

Ubuntu22.04安装paddle

查看系统版本信息 使用命令lsb_release -a查看系统版本 rootLAIS01:~# lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.5 LTS Release: 22.04 Codename: jammy查看系统支持的cuda版本&#xff0c;使用命令nvidia-smi&#…

Llama 3.2来了,多模态且开源!AR眼镜黄仁勋首批体验,Quest 3S头显价格低到离谱

如果说 OpenAI 的 ChatGPT 拉开了「百模大战」的序幕&#xff0c;那 Meta 的 Ray-Ban Meta 智能眼镜无疑是触发「百镜大战」的导火索。自去年 9 月在 Meta Connect 2023 开发者大会上首次亮相&#xff0c;短短数月&#xff0c;Ray-Ban Meta 就突破百万销量&#xff0c;不仅让马…

HT6872 4.7W防削顶单声道D类音频功率放大器

■ 特点 防削顶失真功能(Anti-Clipping Function,ACF) 优异的全带宽EMI抑制性能 免滤波器数字调制&#xff0c;直接驱动扬声器 输出功率 1.40W(VDD3.6V,RL4Ω,THDN10%) 2.80W(VDD5.0V,RL4Ω,THDN10%) 4.70W(VDD6.5V,RL4Ω,THDN10%) 高信噪比SNR:95dB(VDD6.5V,Av24dB. THDN1%) 低…

监控IDS和IPS增强网络安全性

入侵检测系统&#xff08;IDS&#xff09;和入侵防御系统&#xff08;IPS&#xff09;是当今使用的最复杂的网络安全设备之一&#xff0c;它们检查网络数据包并阻止可疑数据包&#xff0c;并提醒管理员有关攻击企图的信息。 在当今威胁不断变化的网络环境中&#xff0c;防火墙…

学习threejs,添加环境光和点光源

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言二、&#x1f340;绘制任意字体模型…

人工智能之机器学习常见算法

摘要 之前一直对机器学习很感兴趣,一直没时间去研究,今天刚好是周末,有时间去各大技术论坛看看,刚好看到一篇关于机器学习不错的文章,在这里就分享给大家了. 机器学习无疑是当前数据分析领域的一个热点内容。很多人在平时的工作中都或多或少会用到机器学习的算法。这里IT经理网…

【Linux实践】实验六:LINUX系统管理

【Linux实践】实验六&#xff1a;LINUX系统管理 实验目的实验内容实验步骤及结果1. 包管理工具2. VMware Tools3. 修改主机名4. 网络配置① 临时修改② 永久修改 5. 查找文件6. 前后台执行7. 查看进程8. 结束进程 实验目的 4、掌握Linux下软件包管理&#xff0c;包括命令rpm、…

公交IC卡收单管理系统 多处 SQL注入致RCE漏洞复现

0x01 产品简介 公交IC卡收单管理系统是城市公共交通领域中不可或缺的一部分,它通过集成先进的集成电路技术(IC卡)实现了乘客便捷的支付方式,并有效提高了公共交通运营效率。系统集成了发卡、充值、消费、数据采集、查询和注销等多个功能模块,为公交公司和乘客提供了全面、…

领夹麦克风哪个品牌音质最好,主播一般用什么麦克风

在这个信息爆炸的时代&#xff0c;清晰的声音传达显得尤为重要。无论是激情澎湃的演讲&#xff0c;还是温馨动人的访谈&#xff0c;一款优质的无线领夹麦克风都能让声音清晰的传播。但市场上产品繁多&#xff0c;如何挑选出性价比高、性能卓越的无线领夹麦克风呢&#xff1f;本…

c4d.python 旋转一个对象

How to Rotate an Object 第一种方法 import c4ddef main():selected doc.GetActiveObject()if selected:#获取这个物体的矩阵,设置它的偏移再设置回来.mg selected.GetMg()mg c4d.utils.MatrixRotY(c4d.utils.DegToRad(45.))selected.SetMg(mg)main() 第二种方法 import…

图书系统|图书个性化推荐系统|基于springboot的图书个性化推荐系统设计与实现(源码+数据库+文档)

图书个性化推荐系统目录 目录 基于springboot的图书个性化推荐系统设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 1、实体ER图 2、具体的表设计如下所示&#xff1a; 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#x…

Web 自动化实战经验硬核总结

一、元素定位常用方法 1. xpath规则说明 "/" : 表示从根节点选取 "//" : 从匹配选择的当前节点选择 "" : 选取属性 "*" : 匹配任何元素节点 "*" : 匹配任何属性节点 1.1 属性使用说明 placeholder 用法&#xff1a…

游戏录制没有声音怎么办?简单的解决方法分享

在享受游戏乐趣的同时&#xff0c;不少玩家也喜欢通过录制游戏视频来分享自己的精彩瞬间或是攻略心得。然而&#xff0c;有时在满心欢喜地开始录制后&#xff0c;却发现录制的视频竟然没有声音&#xff0c;这无疑是一大遗憾&#xff0c;今天我们就来看看这个问题怎么解决吧~ 游…

vue 中获取数值但是只获取到了 Promise 属性,获取不到其中的值

左边的请求能获取到数据&#xff0c;右边的不行&#xff1f; 改成这样即可

即插即用篇 | YOLOv8 引入单头视觉Transformer模块 | CVPR 2024

本改进已同步到YOLO-Magic框架! 最近,高效的视觉Transformer在资源受限的设备上以低延迟表现出了出色的性能。传统上,它们在宏观层面上采用44的Patch嵌入和四阶段结构,而在微观层面上使用多头配置的复杂注意力机制。本文旨在通过内存高效的方式解决各个设计层面的计算冗余问…

Python 从入门到实战28(文件的读操作)

我们的目标是&#xff1a;通过这一套资料学习下来&#xff0c;通过熟练掌握python基础&#xff0c;然后结合经典实例、实践相结合&#xff0c;使我们完全掌握python&#xff0c;并做到独立完成项目开发的能力。 上篇文章我们讨论了文件的打开、创建、关闭的相关知识。今天我们将…

9_25_对话框

QColorDialog&#xff08;调色板对话框&#xff09; void MainWindow::on_pushButton_clicked() { // //创建一个调色板对话框 // QColorDialog* dialog new QColorDialog(this); // //设置调色板对话框的初始值,不调整默认是白色 // dialog->setCurrentColor(…

edu某智慧平台 ExpDownloadService.aspx接口任意文件读取漏洞复现 [附POC]

文章目录 edu某智慧平台 ExpDownloadService.aspx接口任意文件读取漏洞复现 [附POC]0x01 前言0x02 漏洞环境0x03 漏洞复现1.访问漏洞环境2.构造POC3.复现edu某智慧平台 ExpDownloadService.aspx接口任意文件读取漏洞复现 [附POC] 0x01 前言 免责声明:请勿利用文章内的相关技…