Linux串口应用编程

在Linux系统中,操作设备的统一接口就是:open/ioctl/read/write
对于UART,又在ioctl之上封装了很多函数,主要是用来设置行规程。
所以对于UART,编程的套路就是:

  • 使用open函数打开串口
  • 设置行规程,比如波特率、数据位、停止位、检验位、RAW模式、一有数据就返回
  • read/write数据

    在这里插入图片描述

1. 打开串口

由于串行端口是一个文件,因此使用open(2)函数来访问它。C语言代码示例如下。

1.1 示例

#include <stdio.h>   /* 标准输入/输出定义 */
#include <string.h>  /* 字符串函数定义 */
#include <unistd.h>  /* UNIX标准函数定义 */
#include <fcntl.h>   /* 文件控制定义 */
#include <errno.h>   /* 错误号定义 */
#include <termios.h> /* POSIX终端控制定义 */

// 成功时返回文件描述符,错误时返回-1。
int open_port(void){
  int fd; /* 端口的文件描述符 */
  fd = open("/dev/ttyf1", O_RDWR | O_NOCTTY | O_NDELAY);
  if (fd == -1){// 打开端口失败
    perror("open_port: Unable to open /dev/ttyf1 - ");
  }
  else
    fcntl(fd, F_SETFL, 0);
  return (fd);
}

其他系统可能需要相应的设备文件名,但除此之外代码是相同的。

1.2 open函数的标志位

当我们打开设备文件时,我们使用了另外两个标志以及读+写模式:

fd = open("/dev/ttyf1", O_RDWR | O_NOCTTY | O_NDELAY);

其中,

  • O_NOCTTY :表示告诉操作系统,应用程序(进程)打开串口之后,不要把程序当作控制终端。如果指定这一点,那么任何输入(如键盘中止信号等)都将影响进程。
  • O_NDELAY:表示告诉操作系统,应用程序(进程)不关心DCD信号线的状态,即不关心端口的另一端是否启动并运行。如果没有指定这个标志,进程将被置于休眠状态,直到DCD信号线是空间电压。

2. 配置串口

配置串口也就是设置行规程,行规程的参数用结构体struct termios来表示。设置行规程就是设置该结构体中成员的值。

2.1 结构体struct termios

结构体struct termios定义如下:

在这里插入图片描述

struct termios{
	unsigned short c_iflag;   /* 输入模式标志*/
	unsigned short c_oflag;   /* 输出模式标志*/
	unsigned short c_cflag;   /* 控制模式标志*/
	unsigned short c_lflag;   /* 区域模式标志或本地模式标志或局部模式*/
	unsigned char c_line;     /* 行控制line discipline */
	unsigned char c_cc[NCC];  /* 控制字符特性*/
};

2.2 struct termios作用

struct termios被用来提供一个健全的线路设置集合,如果这个端口在被用户初始化前使用. 驱动初始化这个变量使用一个标准的数值集,它拷贝自 tty_std_termios 变量. tty_std_termostty 核心被定义为:

struct termios tty_std_termios = {
	.c_iflag = ICRNL | IXON;
	.c_oflag = OPOST | ONLCR;
	.c_cflag = B38400 | CS8 | CREAD | HUPCL;
	.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
	.c_cc = INIT_C_CC;
};

这个 struct termios 结构用来持有所有的当前线路设置,给这个 tty 设备的一个特定端口。这些线路设置控制当前波特率。数据大小。数据流控设置。以及许多其他值。

2.3 struct termios成员介绍

2.3.1 c_iflag标志常量:Input mode ( 输入模式)

输入模式成员c_iflag控制对端口上接收到的字符所做的任何输入处理。c_iflag中存储的最终值由下表中选项的按位或。

常量 描述
INPCK 启用奇偶校验
IGNPAR 忽略奇偶校验错误
PARMRK 标记奇偶校验错误
ISTRIP 去掉奇偶校验位
IXON 启用输出的 XON/XOFF 流控制
IXOFF 启用输入的 XON/XOFF 流控制
IXANY (不属于 POSIX.1;XSI) 允许任何字符来重新开始输出
IGNBRK 忽略输入中的 BREAK 状态。 (忽略命令行中的中断)
BRKINT 当检测到中断条件时发送SIGINT
INLCR 将输入中的 NL 翻译为 CR。(将收到的换行符号转换为Return)
IGNCR 忽略输入中的回车
ICRNL 将输入中的回车翻译为新行 (除非设置了 IGNCR)(否则当输入信号有 CR 时不会终止输入)
IUCLC (不属于 POSIX) 将输入中的大写字母映射为小写字母
IMAXBEL (不属于 POSIX) 当输入队列满时响零。Linux 没有实现这一位,总是将它视为已设置

2.3.2 c_oflag 标志常量: Output mode ( 输出模式)

c_oflag成员包含输出过滤选项。与输入模式一样,您可以选择已处理原始数据输出。c_oflag 中存储的最终值由下表中选项的按位或。

常量 描述
OPOST 启用具体实现自行定义的输出处理(未设置=原始输出)
OLCUC (不属于 POSIX) 将输出中的小写字母映射为大写字母
ONLCR (XSI) 将输出中的新行符映射为回车-换行
OCRNL 将输出中的回车映射为新行符
ONOCR 不在第 0 列输出回车
ONLRET 不输出回车
OFILL 发送填充字符作为延时,而不是使用定时来延时
OFDEL (不属于 POSIX) 填充字符是 ASCII DEL (0177)。如果不设置,填充字符则是 ASCII NUL
NLDLY 新行延时掩码。取值为 NL0 和 NL1
CRDLY 回车延时掩码。取值为 CR0,CR1,CR2,或 CR3
BSDLY 回退延时掩码。取值为 BS0 或 BS1。(从来没有被实现过)
VTDLY 竖直跳格延时掩码。取值为 VT0 或 VT1
IUCLC (不属于 POSIX) 将输入中的大写字母映射为小写字母
FFDLY 进表延时掩码。取值为 FF0 或 FF1

更多选项如下图所示:

在这里插入图片描述


一般有两种输出模式可供选择:
(1)选择已处理输出
通过在c_oflag成员中设置OPOST选项来选择处理后的输出:

options.c_oflag |= OPOST;

在所有不同的选项中,目前只能使用ONLCR选项,它将换行符映射为CR-LF对。其余的输出选项主要是历史上的,可以追溯到行打印机和终端无法跟上串行数据流的时候。
(2)选择原始输出
通过重置c_oflag成员中的OPOST选项来选择原始输出:

options.c_oflag &= ~OPOST;

OPOST选项被禁用时,c_oflag中的所有其他选项位都会被忽略。

2.3.3 c_cflag 标志常量: Control mode ( 控制模式)

c_cflag成员控制波特率、数据位数、奇偶校验、停止位和硬件流控制。所有支持的配置都有常量。

c_cflag中存储的最终值由下表中选项确定。

常量 描述
CBAUD (不属于 POSIX) 波特率掩码 (4+1 位)
OLCUC (不属于 POSIX) 扩展的波特率掩码 (1 位),包含在 CBAUD 中
CSIZE 字符长度掩码(传送或接收字元时用的位数)。取值为 CS5(传送或接收字元时用5bits),CS6,CS7,或 CS8
CSTOPB 设置两个停止位,而不是一个
CREAD 打开接受者
PARENB 允许输出产生奇偶信息以及输入的奇偶校验(启用同位产生与侦测)
PARODD 输入和输出是奇校验(使用奇同位而非偶同位)
HUPCL 在最后一个进程关闭设备后,降低 modem 控制线 (挂断)
CLOCAL 忽略 modem 控制线
LOBLK (不属于 POSIX) 从非当前 shell 层阻塞输出(用于 shl )
CIBAUD (不属于 POSIX) 输入速度的掩码。CIBAUD 各位的值与 CBAUD 各位相同,左移了 IBSHIFT 位
CRTSCTS (不属于 POSIX) 启用 RTS/CTS (硬件) 流控制

在这里插入图片描述


c_cflag成员包含两个应该始终启用的选项,CLOCALCREAD。这将确保您的程序不会成为端口的“所有者”,受到零星的作业控制和挂起信号的影响,并且串行接口驱动程序将读取传入的数据字节。

不要直接初始化c_cflag(或任何其他标志)成员。应该始终使用按位的ANDORNOT操作符来设置或清除成员中的位。不同的操作系统版本可以以不同的方式使用位,因此使用位操作符将防止破坏新串行驱动程序中所需的位标志。

2.3.4 c_lflag 标志常量: Local mode ( 局部模式)

本地模式成员c_lflag控制串口驱动程序如何管理输入字符。通常,将为规范或原始输入配置c_lflag成员。c_cflag中存储的最终值由下表中选项确定。

常量 描述
ISIG 使能SIGINTR、SIGSUSP、SIGDSUSP和SIGQUIT信号
ICANON 启用规范化输入(否则为raw)
XCASE (不属于 POSIX; Linux 下不被支持) 如果同时设置了 ICANON,终端只有大写。输入被转换为小写,除了有前缀的字符。输出时,大写字符被前缀(某些系统指定的特定字符) ,小写字符被转换成大写。
ECHO 启用输入字符的回显
ECHOE 如果同时设置了 ICANON,字符 ERASE 擦除前一个输入字符,WERASE 擦除前一个词
ECHOK 如果同时设置了 ICANON,字符 KILL 删除当前行
ECHONL 如果同时设置了 ICANON,回显字符 NL,即使没有设置 ECHO
NOFLSH 禁止在产生 SIGINT,SIGQUIT 和 SIGSUSP 信号时刷新输入和输出队列,即关闭queue中的flush
IEXTEN 启用扩展功能
ECHOCTL 如果同时设置了 ECHO,除了 TAB,NL,START,和 STOP 之外的 ASCII 控制信号被回显为 ^X,这里 X 是比控制信号大 0x40 的 ASCII 码。例如,字符 0x08 (BS) 被回显为 ^H
ECHOPRT 如果同时设置了 ICANON 和 IECHO,字符在删除的同时被打印
CRTSCTS (不属于 POSIX) 启用 RTS/CTS (硬件) 流控制

一般有两种输入模式可供选择:
(1)选择规范输入
规范输入是面向行的。输入字符被放入缓冲区,用户可以交互地编辑缓冲区,直到收到CR(回车)或LF(换行)字符。
当选择此模式时,通常选择ICANONECHOECHO选项:

options.c_lflag |= (ICANON | ECHO | ECHOE);

(2)选择原始输入
原始输入未经处理。当接收到输入字符时,它们将完全按照接收到的方式传递。通常,当使用原始输入时,您将取消选择ICANON,ECHO,ECHOEISIG选项:

options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

2.3.5 c_cc 数组:特殊控制字元

UNIX串行接口驱动程序提供了指定字符和数据包超时的能力。c_cc数组中的两个元素用于超时:VMINVTIME。在规范输入模式下或通过openfcntl在文件上设置NDELAY选项时,会忽略超时。

VMIN指定要读取的最小字符数。如果设置为0,则VTIME值指定等待读取每个字符的时间。请注意,这并不意味着对N个字节的读取调用将等待N个字符进入。相反,超时将应用于第一个字符,read调用将返回立即可用的字符数(最多可达您请求的字符数)。

如果VMIN不为零,则VTIME指定等待读取第一个字符的时间。如果在给定的时间内读取一个字符,则任何读取将阻塞(等待),直到读取所有VMIN字符。也就是说,一旦读取了第一个字符,串行接口驱动程序期望接收整个字符包(VMIN字节总数)。如果在允许的时间内没有读取任何字符,则调用read返回0。此方法允许您告诉串行驱动程序您需要恰好N个字节,并且任何读调用将返回0或N个字节。然而,超时只适用于第一个字符读取,所以如果由于某种原因驱动程序错过了N字节包中的一个字符,那么read调用可能会永远阻塞,等待额外的输入字符。

VTIME指定等待传入字符的时间,以十分之一秒为单位。如果VTIME设置为0(默认值),读取将无限期阻塞(等待),除非在端口上设置NDELAY选项openfcntl

VMINVTIME的组合方式如下:
(1)VMIN = 0,VTIME =0
read立即回传,否则传回 0,不读取任何字元
(2)VMIN = 0,VTIME >0
read传回读到的字元,或在十分之一秒后传回VTIME
(3)VMIN > 0,VTIME =0
read会等待,直到VMIN字元可读
(4)VMIN > 0,VTIME > 0
每一格字元之间计时器即会被启动
read会在读到VMIN字元,传回值或VTIME的字元计时(1/10秒)超过时将值传回

2.4 与结构体struct termios相关的函数

函数命名解释:

  • tc:terminal contorl
  • cf:control flag

2.4.1 tcgetattr()与tcsetattr()

(1)tcgetattr()函数:get terminal attributes,获得终端的属性
原型:

#include <termios.h>
#include <unistd.h>

int tcgetattr(int fd, struct termios *termios_p);

作用:取得终端介质(fd)初始值,并把其值 赋给temios_p; 函数可以从后台进程中调用;但是,终端属性可能被后来的前台进程所改变。

(2)tcsetattr() 函数:set terminal attributes,修改终端参数
原型:

#include <termios.h>
#include <unistd.h>

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

作用:设置与终端相关的参数 ,使用 termios_p 引用的 termios 结构。optional_actionstcsetattr函数的第二个参数)指定了什么时候改变会起作用,可以使用的值如下:

  • TCSANOW:改变立即发生
  • TCSADRAIN:改变在所有写入 fd 的输出都被传输后生效。这个函数应当用于修改影响输出的参数时使用。(当前输出完成时将值改变)
  • TCSAFLUSH :改变在所有写入 fd 引用的对象的输出都被传输后生效,所有已接受但未读入的输入都在改变发生前丢弃(同TCSADRAIN,但会舍弃当前所有值)。

2.4.2 tcflush()

原型:

int tcflush(int fd, int queue_selector);

作用:丢弃要写入 引用的对象,但是尚未传输的数据,或者收到但是尚未读取的数据,取决于 queue_selector 的值。 queue_selector的取值有:

  • TCIFLUSH :刷新收到的数据但是不读
  • TCOFLUSH :刷新写入的数据但是不传送
  • TCIOFLUSH :同时刷新收到的数据但是不读,并且刷新写入的数据但是不传送

2.4.3 tcflow()

原型:

int tcflow(int fd, int action);

作用:挂起 fd 引用的对象上的数据传输或接收,取决于 action 的值。 action 取值有:

  • TCOOFF :挂起输出
  • TCOON :重新开始被挂起的输出
  • TCIOFF :发送一个 STOP 字符,停止终端设备向系统传送数据
  • TCION :发送一个 START 字符,使终端设备向系统传输数据

打开一个终端设备时的默认设置是输入和输出都没有挂起。

2.4.4 波特率函数

波特率函数被用来获取和设置 termios结构体中输入和输出波特率的值。新值不会马上生效,直到成功调用了 tcsetattr() 函数。
(1)cfgetospeed()函数
原型:

speed_t cfgetispeed(const struct termios *termios_p);

作用:返回 termios_p 指向的 termios 结构中存储的输出波特率。返回存储在终端结构中的输入波特率。
(2)cfsetispeed()函数:sets the input baud rate,设置输入波特率
原型:

int cfsetispeed(struct termios *termios_p, speed_t speed);

作用:设置 termios 结构中存储的输入波特率为 speed。如果输入波特率被设为0,实际输入波特率将等于输出波特率。
(3)cfsetospeed()函数:sets the output baud rate,设置输出波特率
原型:

int cfsetospeed(struct termios *termios_p, speed_t speed);

作用:设置 termios 结构中存储的输出波特率为 speed

(4)cfsetspeed()函数:同时设置输入、输出波特率
原型:

int cfsetspeed(struct termios *termios_p, speed_t speed);

作用:cfsetspeed()是一个4.4BSD扩展。它接受与cfsetispeed()相同的参数,并设置输入和输出速度。
(5)波特率大小设置选择
如图:

在这里插入图片描述

3. Linux串口应用编程实例

下面给出了串口配置的完整的函数。通常,为了函数的通用性,通常将常用的选项都在函数中列出,这样可以大大方便以后用户的调试使用。该设置函数如下所示:

3.1 串口配置的函数

// fd:设备文件描述符;nSpeed:需要设置的波特率;nBits:需要设置的数据位数;nEvent:奇偶校验位;nStop:停止位
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop){
	struct termios newtio,oldtio;

	/*保存测试现有串口参数设置,在这里如果串口号等出错,会有相关的出错信息*/
	if  ( tcgetattr( fd,&oldtio)  !=  0) { 
		perror("SetupSerial 1");
		return -1;
	}
	
	//将 newtio 清零
	bzero( &newtio, sizeof( newtio ) );

	/*步骤一,设置字符大小*/
	newtio.c_cflag  |=  CLOCAL | CREAD; 
	newtio.c_cflag &= ~CSIZE; 

	/*设置数据位*/
	switch( nBits ){
		case 7:
			newtio.c_cflag |= CS7;
			break;
		case 8:
			newtio.c_cflag |= CS8;
			break;
	}

	/*设置奇偶校验位*/
	switch( nEvent ){
		case 'O': //奇数
			newtio.c_cflag |= PARENB;
			newtio.c_cflag |= PARODD;
			newtio.c_iflag |= (INPCK | ISTRIP);
			break;

		case 'E': //偶数
			newtio.c_iflag |= (INPCK | ISTRIP);
			newtio.c_cflag |= PARENB;
			newtio.c_cflag &= ~PARODD;
			break;
		case 'N':  //无奇偶校验位
			newtio.c_cflag &= ~PARENB;
			break;
	}

	/*设置波特率*/
	switch( nSpeed ){
		case 2400:
			cfsetispeed(&newtio, B2400);
			cfsetospeed(&newtio, B2400);
			break;
		case 4800:
			cfsetispeed(&newtio, B4800);
			cfsetospeed(&newtio, B4800);
			break;
		case 9600:
			cfsetispeed(&newtio, B9600);
			cfsetospeed(&newtio, B9600);
			break;
		case 115200:
			cfsetispeed(&newtio, B115200);
			cfsetospeed(&newtio, B115200);
			break;
		case 460800:
			cfsetispeed(&newtio, B460800);
			cfsetospeed(&newtio, B460800);
			break;
		default:
			cfsetispeed(&newtio, B9600);
			break;
	}

	/*设置停止位*/
	if( nStop == 1 )
		newtio.c_cflag &=  ~CSTOPB;
	else if ( nStop == 2 )
		newtio.c_cflag |=  CSTOPB;

	/*设置等待时间和最小接收字符*/
	newtio.c_cc[VTIME]  = 0;
	newtio.c_cc[VMIN] = 0;

	/*处理未接收字符*/
	tcflush(fd,TCIFLUSH);

	/*激活新配置*/
	if((tcsetattr(fd,TCSANOW,&newtio))!=0){
		perror("com set error");
		return -1;
	}
	printf("set done!\n");
	return 0;
}

3.2 打开串口的函数

下面给出了一个完整的打开串口的函数,同样写考虑到了各种不同的情况。程序如下所示:

/*打开串口函数*/
int open_port(int fd,int comport){
	char *dev[]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2"};

	//串口 1
	if (comport==1){
		fd = open( "/dev/ttyS0", O_RDWR|O_NOCTTY|O_NDELAY);
		if (-1 == fd){
			perror("Can't Open Serial Port");
			return(-1);
		}
	}
	else if(comport==2){//串口 2
		fd = open( "/dev/ttyS1", O_RDWR|O_NOCTTY|O_NDELAY);
		if (-1 == fd){
			perror("Can't Open Serial Port");
			return(-1);
		}
	}
	else if (comport==3){//串口 3
		fd = open( "/dev/ttyS2", O_RDWR|O_NOCTTY|O_NDELAY);
		if (-1 == fd){
			perror("Can't Open Serial Port");
			return(-1);
		}
	}

	/*恢复串口为阻塞状态*/
	if(fcntl(fd, 0)<0)
		printf("fcntl failed!\n");
	else
		printf("fcntl=%d\n",fcntl(fd,0));

	/*测试是否为终端设备*/
	if(isatty(STDIN_FILENO)==0)
		printf("standard input is not a terminal device\n");
	else
		printf("isatty success!\n");
		
	printf("fd-open=%d\n",fd);

	return fd;
}

3.3 从串口中读取数据

//
int read_datas(int fd, char *rcv_buf,int rcv_wait){
	int retval;

	fd_set rfds;

	struct timeval tv;

	int ret,pos;

	tv.tv_sec = rcv_wait;      // wait 2.5s
	tv.tv_usec = 0;

	pos = 0; // point to rceeive buf

	while (1){
		FD_ZERO(&rfds);

		FD_SET(fd, &rfds);

		retval = select(fd+1 , &rfds, NULL, &tv);

		if (retval == -1){
			perror("select()");
			break;
		}
		else if (retval){// pan duan shi fou hai you shu ju
			ret = read(fd, rcv_buf+pos, 2048);
			pos += ret;
	
			if (rcv_buf[pos-2] == '\r' && rcv_buf[pos-1] == '\n'){
				FD_ZERO(&rfds);
				FD_SET(fd, &rfds);
	
				retval = select(fd+1 , &tv);
	
				if (!retval) break;// no datas,break
		
			}
		}
		else{
			printf("No data\n");
			break;
		}

	}
	return 1;
}

3.4 向串口传数据

int send_data(int fd, char *send_buf){
	ssize_t ret;
	ret = write(fd,send_buf,strlen(send_buf));

    if (ret == -1){
		printf ("write device %s error\n", DEVICE_TTYS);
		return -1;
	}
    return 1;
}

参考

[1] https://digilander.libero.it/robang/rubrica/serial.htm
[2] https://blog.csdn.net/yemingzhu163/article/details/5897156
[3] https://www.cnblogs.com/feisky/archive/2010/05/21/1740893.html

原文地址:https://blog.csdn.net/weixin_45003868/article/details/130263090

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


linux常用进程通信方式包括管道(pipe)、有名管道(FIFO)、信号(signal)、消息队列、共享内存、信号量、套接字(socket)。管道用于具有亲缘关系的进程间通信,有名管道的每个管道具有名字,使没有亲缘关系的进程间也可以通信。信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除
Linux性能观测工具按类别可分为系统级别和进程级别,系统级别对整个系统的性能做统计,而进程级别则具体到进程,为每个进程维护统计信息。&#xD;&#xA;&#xD;&#xA;按实现原理分,可分为基于计数器和跟踪以及剖析。含义如下:&#xD;&#xA;&#xD;&#xA;计数器:内核维护的统计数据,通常为无符号整型,用于对发生的事件计数,比如,网络包接收计数器,磁
本文详细介绍了curl命令基础和高级用法,包括跳过https的证书验证,详细追踪整个交互过程,可用于调用网络后端接口,诊断http和https网络服务故障。
本文包含作者工作中常用到的一些命令,用于诊断网络、磁盘占满、fd泄漏等问题。命令包括ping、fping、tcpdump、lsof、netstat、/proc/$pid/fd、du、grep、traceroute、dig。
linux的平均负载表示运行态和就绪态及不可中断状态(正在io)的进程数目,用uptime查看到负载很高,既有可能是CPU利用率高,也可能是大量在等待io的进程导致,用mpstat查看每个CPU的使用情况,查看CPU的使用率或者CPU花在等待io的时间,接着用pidstat定位具体的进程
CPU上下文频繁切换会导致系统性能下降,切换分为进程切换、线程切换及中断切换,进程切换的开销较大,除了需要保存寄存器和程序计数器中的值还需保存全局变量、栈等到内存中,以便下次运行恢复,而同一进程中的线程切换开销会小很多,只需更新寄存器和线程独有的栈,共享资源如打开的文件、全局变量等无需切换,当硬件中
1.top命令 作用:该命令可以按CPU使用.内存使用和执行时间对任务进行排序,常用来监控系统中占用CPU或内存较高的程序及CPU和内存的负载。 默认视图: 当想看系统负载时,可观察汇总的%CPU中的us用户进程和sy系统进程是否占用CPU很高,相加接近100%就说明占用很高了,有些程序可能得不到及
文章浏览阅读1.8k次,点赞63次,收藏54次。Linux下的目录权限!!!粘滞位!!!超详解!!!
文章浏览阅读1.6k次,点赞44次,收藏38次。关于Qt的安装、Windows、Linux、MacBook_mack book 安装qt
本文介绍了使用shell脚本编写一个 Hello
文章浏览阅读1.5k次,点赞37次,收藏43次。【Linux】初识Linux——了解操作系统的发展历史以及初次体验Linux编程环境
文章浏览阅读3k次,点赞34次,收藏156次。Linux超详细笔记,个人学习时很认真的记录的,觉得好的麻烦点个赞。
文章浏览阅读6.8k次,点赞109次,收藏114次。【Linux】 OpenSSH_9.3p1 升级到 OpenSSH_9.5p1(亲测无问题,建议收藏)_openssh_9.5p1
文章浏览阅读3.5k次,点赞93次,收藏78次。初识Linux中的线程,理解线程的各种概念,理解进程地址空间中的页表转换,介绍pthread线程库并理解线程库!
文章浏览阅读863次。出现此问题为Linux文件权限问题,解决方案为回到引擎目录执行命令。输入用户密码后运行./UnrealEditor。_increasing per-process limit of core file size to infinity.
文章浏览阅读2.9k次。使用文本编辑器:打开CSV文件,并使用文本编辑器(如Notepad++、Sublime Text、Visual Studio Code等)来查看文件的字符编码格式。通常在编辑器的底部状态栏或设置中可以找到当前编码的显示。请注意,上述方法并非绝对准确,特别是当文件没有明确的编码标识时。因此,如果你发现CSV文件在不同的工具或方法中显示不同的编码格式,可能需要进行进一步的分析和判断,或者尝试使用不同的编码转换方法。该命令将输出文件的MIME类型和编码信息。使用命令行工具:在命令行中,你可以使用。_shell读取csv文件逐行处理
本文介绍了如何在Linux系统中升级gcc版本,以便更好地支持C++11及以上版本的新特性。通过升级gcc,可以提升编译器的功能和性能,获得更好的开发体验。详细的步骤和方法请参考原文链接。
文章浏览阅读4.4k次,点赞6次,收藏19次。Mosquitto是一个开源的MQTT消息代理服务器。MQTT是一个轻量级的、基于发布/订阅模式的消息传输协议。 mosquitto的安装使用比较简单,可以方便的来进行一些测试。_linux mosquitto
文章浏览阅读7.2k次,点赞2次,收藏12次。Linux中,用于根目录下有一个.ssh目录,保存了ssh相关的key和一些记录文件。_~/.ssh/
文章浏览阅读4.5k次,点赞5次,收藏18次。首先需要安装 snmp ,使用下面的命令进行安装安装完毕之后,使用下面的命令查看是否安装成功当命令行显示如图即为安装成功。_snmp工具