Linux系统远程操作和程序编译

发布于:2025-04-15 ⋅ 阅读:(22) ⋅ 点赞:(0)

Linux系统远程操作和程序编译

一、了解和熟悉Linux系统的远程终端登录、远程图形桌面访问、 X图形窗口访问和FTP文件传输操作

将虚拟机Ubuntu系统的网络连接设置为“桥接模式”,并配置Ubuntu的IP、网关参数,保证其他同学的win10系统能够ping通你的Ubuntu; 将树莓派配置在自动联网模式,保证其他同学的win10系统能够ping通你的Ubuntu; 然后,在Ubuntu和树莓派上分别用 sudo adduser添加2个用户名classmate1,、classmate2,密码均为123456;

ubantu
1. 将虚拟机Ubuntu系统的网络连接设置为“桥接模式”,并配置Ubuntu的IP、网关参数,保证其他同学的win10系统能够ping通你的Ubuntu;在Ubuntu和树莓派上分别用 sudo adduser添加2个用户名classmate1,、classmate2,密码均为123456;

(1)设置桥接模式
在这里插入图片描述

Win10主机的网络查看:

ipconfig

在这里插入图片描述

(2)配置Ubantu的网络参数:使用静态ip配置sudo nano /etc/netplan/01-netcfg.yaml
保存文件并运行以下命令应用配置:在这里插入图片描述

使用另一台电脑使用ping命令观察是否成功:在这里插入图片描述

(3)添加用户

在这里插入图片描述
在这里插入图片描述

(4)安装ssh服务

sudo apt updatesudo apt install openssh-serversudo systemctl enable sshsudo systemctl start ssh

让同学使用创建账号在win10下用putty或xshell等远程登录你的Ubunt系统、树莓派系统(注意要打开SSH服务)

ubantu

使用Putty连接虚拟机
打开Putty输入自己的虚拟机的IP地址,port选为22。随后点击Open进行访问。
在这里插入图片描述

进入终端,使用我们创建的账号进入虚拟机
在这里插入图片描述

树莓派

打开PuTTY,在Session中输入:

Host Name: 树莓派/Ubuntu服务器的IP地址

Port: 22(默认SSH端口)

配置X11转发:
Connection > SSH > X11
勾选"Enable X11 forwarding"
X display location设为"localhost:0"
在这里插入图片描述

在这里插入图片描述

如果正确配置了PuTTY的X11转发,不需要手动设置DISPLAY变量。SSH连接会自动设置正确的DISPLAY环境变量
可以通过以下命令验证:

echo $DISPLAY

在这里插入图片描述

若没有,可以通过以下命令进行DISPLAY环境配置


set DISPLAY=<电脑IP地址>:0



测试图形程序
输入以下命令进行测试:

xeyes 


在这里插入图片描述

通过Putty进行图像界面软件的运行
图形界面文件的打开

首先通过VNC远程登录到树莓派系统桌面
由于博主之前已经配置好桌面系统环境,这里就不赘述了,没下载VNC的可以看这个博客:https://blog.csdn.net/2201_75516394/article/details/146102066?spm=1001.2014.3001.5501

输入以下命令打开对应的图形界面


gedit <文件名>



若没下载gedit,可以通过下面命令进行下载


sudo apt updatesudo apt install gedit -y




可以在桌面系统看见helloworld.c文件已经被打开
在这里插入图片描述
在这里插入图片描述

图形界面软件的打开

输入以下命令


firefox



可以看到文件已经成功上传。

3. 让同学在win10下用 ftp或xshel等软件l远程登录你的Ubunt系统、树莓派系统,上传和下载文件(注意要打开SSH服务)

ubantu

我们使用FileZilla

输入完主机、用户名、密码、端口号等信息之后,连接,随后在左侧选择要上传的文件夹即可

在这里插入图片描述

在客户端windows下安装X server仿真软件(这里我们使用免费软件 Xming), 以及终端软件,这次实验采用 putty。

安装好之后打开让它在后台运行。

打开PuTTY,进入Connection→SSH→Auth→X11 forwarding并勾选,然后使用classmate1访问虚拟机

在这里插入图片描述

输入指令连接windows系统:

set DISPLAY=xxx.xxx.xxx.xxx:0

输入命令打开windows下载的Xing:

gedic

在这里插入图片描述

在这里插入图片描述

树莓派

在电脑命令行中使用ssh命令登录树莓派
在这里插入图片描述

sftpd的下载
输入以下命令下载vsftpd:sudo apt-get install vsftpd
在这里插入图片描述

修改配置文件
输入以下命令进入文件vsftpd.v并对应将图片中圈出的语句前的#删掉


cd /etc/sudo nano vsftpd.conf



在这里插入图片描述

重新启动服务

sudo service vsftpd restart

ftp远程登录树莓派
打开cmd命令行
输入ftp <树莓派的IP地址>然后对应输入用户名和密码进行登录
在这里插入图片描述

在这里插入图片描述

文件上传
首先我们在电脑中找到我们要上传的文件路径

然后我们在命令行中写入下面代码

mkdir week8 //新建文件夹,用于存放待会上传的文件ls //查看所有文件夹,可以看见我们新创建的week8cd week8 //打开week8文件夹lcd E:\ //进入本地目录中,LCD 后面跟自己文件所在的目录put helloworld.c //将helloworld.c文件上传至该文件夹中

在这里插入图片描述

通过ls命令我们可以查看该文件是否上传成功

在这里插入图片描述

可以看到文件已经成功上传。

思考题

X窗口协议与远程桌面VNC-viewer协议有什么差异?

X Window System (X11) 的 X 协议和 VNC (Virtual Network Computing) 的 VNC-viewer 协议都是用于远程访问和控制图形用户界面的工具,但它们在设计、功能和使用场景上有一些关键差异:
1. 协议类型
X 协议:是X Window System的一部分,专门设计用于通过网络访问和控制运行X程序的图形界面。X 协议是X Window System的原生协议,提供了丰富的图形界面操作能力。
VNC-viewer 协议:是VNC(Virtual Network Computing)协议的一部分,VNC是一个更通用的远程桌面访问解决方案,支持多种操作系统和多种类型的客户端。VNC-viewer通常用于连接到运行VNC服务器的远程桌面环境。
2. 图形界面
X 协议:提供了完整的图形界面访问能力,允许用户通过网络操作运行的X应用程序,就像在本地机器上操作一样。
VNC-viewer 协议:也提供图形界面访问,但其功能可能受到VNC服务器配置和客户端能力的限制。VNC-viewer通常用于访问远程桌面环境,可能包括多种应用程序和桌面环境。
3. 性能和优化
X 协议:通常针对X Window System进行了优化,提供了较好的性能和较低的延迟,特别是在处理图形密集型任务时。
VNC-viewer 协议:性能可能受到多种因素的影响,包括网络延迟、服务器负载和客户端性能。VNC-viewer可能需要更多的网络带宽来处理图形数据。
4. 安全性
X 协议:安全性可能依赖于X Window System的安全性设置,包括加密和认证机制。
VNC-viewer 协议:VNC提供了一套完整的安全特性,包括加密连接、用户认证和访问控制。VNC-viewer通常用于需要高安全性的环境。
5. 易用性和配置
X 协议:配置可能相对简单,特别是在X Window System环境中。
VNC-viewer 协议:可能需要更多的配置,特别是在设置VNC服务器和客户端时。VNC-viewer通常需要配置网络、安全和用户访问策略。
6. 跨平台支持
X 协议:主要设计用于X Window System环境,对其他操作系统的支持可能有限。
VNC-viewer 协议:VNC提供了跨平台支持,可以在多种操作系统上运行客户端和服务器,包括Linux、Windows、macOS等。

你会发现新建的账号无法使用sudo命令,请问如何解决这个问题?

在 Ubuntu 中,新建的用户无法使用 sudo 命令是因为该用户未被添加到 sudo 用户组(或 /etc/sudoers 文件中未授权)。我们可以通过root账户操作:

切换到root用户:

 su - root

sudo - i

将新用户添加到sudo组:

usermod -aG sudo 新用户名

验证是否生效:

groups 新用户名

三、编写一个打开图片进行特效显示的代码 test1.cpp

3.1 下载安装 opencv
3.1.1 下载安装包并解压

下载安装资源压缩包
在这里插入图片描述

将下载好的压缩包opencv-3.4.11放在主目录文件夹下
在这里插入图片描述

解压缩(打开虚拟机终端,输入命令 unzip opencv-3.4.11.zip)


unzip opencv-3.4.11.zip



在这里插入图片描述

解压缩以后主目录文件夹如下:
在这里插入图片描述

进入到解压后的文件夹中


cd opencv-3.4.11



在这里插入图片描述

3.1.2 使用 cmake安装opencv

(1)首先进入 root 用户,并更新一下

sudo su


sudo apt-get update



在这里插入图片描述

在这里插入图片描述

(2)执行以下命令安装 cmake


sudo apt-get install cmake



在这里插入图片描述
在这里插入图片描述

这里直接按enter键默认继续安装
(3)cmake安装完成
在这里插入图片描述

(4)安装依赖库


sudo apt-get install build-essential libgtk2.0-dev libavcodec-dev libavformat-dev libjpeg.dev 
libtiff5.dev libswscale-dev libjasper-dev  



在这里插入图片描述

(5)创建build文件夹,进入build文件夹
在这里插入图片描述

(6)使用cmake 编译参数


cmake ..



运行结果如下:
在这里插入图片描述

3.1.3 使用make创建并编译安装

(1)在build文件夹下进行
输入以下命令


sudo make



在这里插入图片描述

(2)编译完成
在这里插入图片描述

(3)安装
输入以下命令


sudo make install



在这里插入图片描述

(4)安装完成
在这里插入图片描述

3.1.4 配置环境

(1)修改 opencv.conf文件,打开后的文件是空的,添加opencv库的安装路径:/usr/local/lib
输入以下命令


sudo gedit /etc/ld.so.conf.d/opencv.conf 



在这里插入图片描述

在这里插入图片描述

输入路径/usr/local/lib 并保存,记得点小叉叉退出文件编辑界面
出现警告是正常的
(2)更新系统共享链接


sudo ldconfig



在这里插入图片描述

(3)配置bash,修改 bash.bashrc 文件
输入以下命令


sudo gedit /etc/bash.bashrc



在这里插入图片描述

(4)在文件末尾加入

PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig


export PKG_CONFIG_PATH



在这里插入图片描述

(5)然后执行以下命令使得配置生效

source /etc/bash.bashrc 

在这里插入图片描述

(6)输入以下命令更新


sudo updatedb



在这里插入图片描述

在这里插入图片描述

(7)查看 opencv 的版本信息
如下图所示,说明安装成功
在这里插入图片描述

3.2 打开图片进行特效显示
3.2.1 示例图片

在这里插入图片描述

3.2.2 具体过程

(1)新建文件夹code
输入以下命令创建新的文件夹

mkdir code


cd code



在这里插入图片描述

(2)新建文件 test1.cpp
输入以下命令新建 test1.cpp 文件


vim test1.cpp



在这里插入图片描述

(3)test1.cpp代码

#include <opencv2/highgui.hpp>


#include <opencv2/opencv.hpp>


using namespace cv;


using namespace std;


int main(int argc, char** argv)


{




 CvPoint center;


    double scale = -3; 


 


    IplImage* image = cvLoadImage("lena.jpg");


    argc == 2? cvLoadImage(argv[1]) : 0;


    


    cvShowImage("Image", image);


    


    


    if (!image) return -1;  center = cvPoint(image->width / 2, image->height / 2);


    for (int i = 0;i<image->height;i++)


        for (int j = 0;j<image->width;j++) {


            double dx = (double)(j - center.x) / center.x;


            double dy = (double)(i - center.y) / center.y;


            double weight = exp((dx*dx + dy*dy)*scale);


            uchar* ptr = &CV_IMAGE_ELEM(image, uchar, i, j * 3);


            ptr[0] = cvRound(ptr[0] * weight);


            ptr[1] = cvRound(ptr[1] * weight);


            ptr[2] = cvRound(ptr[2] * weight);


        }


 


    Mat src;Mat dst;


    src = cvarrToMat(image);


    cv::imwrite("test.png", src);


 


    cvNamedWindow("test",1);    imshow("test", src);


     cvWaitKey();


     return 0;


}


输入代码以后,按Esc 输入 :wq保存退出
在这里插入图片描述

vim修改代码,按i进入插入模式;按Esc再输入 :wq 保存并退出
(4)把图片粘贴到code目录下
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
(5)编译 test1.cpp 文件

g++ test1.cpp -o test pkg-config --cflags --libs opencv

在这里插入图片描述

(6)运行
输入以下命令运行

./test

在这里插入图片描述

运行结果
在这里插入图片描述

3.2.3 相关问题

1、请解释 gcc test1.cpp -o test1 pkg-config --cflags --libs opencv这条编译命令,它是如何获得opencv头文件、链接lib库文件的路径的?
命令解析:

gcc:GNU 编译器,用于编译 C/C++ 程序。


test1.cpp:源代码文件,包含 OpenCV 的代码。


-o test1:指定输出的可执行文件名称为 test1。


`pkg-config --cflags --libs opencv`:这是一个子命令用于,动态获取 OpenCV 的编译和链接参数。


pkg-config:一个工具,用于查询已安装库的编译和链接参数。


--cflags:获取 OpenCV 的头文件路径(-I 参数)。


--libs:获取 OpenCV 的库文件路径(-L 参数)和库名称(-l 参数)。


(1)pkg-config --cflags --libs opencv 会返回 OpenCV 的头文件路径和库文件路径,例如:

-I/usr/local/include/opencv4 -L/usr/local/lib -lopencv_core -lopencv_imgproc 
-lopencv_highgui ...

(2)这些参数会被传递给 gcc,确保编译器能够找到 OpenCV 的头文件和库文件。
2、改用make+makefile方式编译 上述程序(用变量命名格式写makefile文件,并包括 clean选项)
将以下内容保存为 Makefile 文件,放在 code 目录下

定义变量


CXX = g++


CXXFLAGS = `pkg-config --cflags opencv`


LDFLAGS = `pkg-config --libs opencv`


SRC = test.cpp


OBJ = test.o


TARGET = test

默认目标


all: $(TARGET)


编译规则


$(TARGET): $(OBJ)


    $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(TARGET) $(OBJ)


 生成对象文件


$(OBJ): $(SRC)


    $(CXX) $(CXXFLAGS) -c $(SRC) -o $(OBJ)

清理


clean:


    rm -f $(OBJ) $(TARGET)


在终端运行以下命令
cd ~/code


make


运行程序

./test


清理编译文件

make clean



3、用cmake方式进行编译
将以下内容保存为 CMakeLists.txt 文件,放在 ~/code 目录下:

#CMake 最低版本要求


cmake_minimum_required(VERSION 3.10)

 项目名称


project(OpenCVTest)


 查找 OpenCV


find_package(OpenCV REQUIRED)


添加可执行文件


add_executable(test test.cpp)


链接 OpenCV 库


target_link_libraries(test ${OpenCV_LIBS})


(1)在 ~/code 目录下创建一个构建目录并进入:

cd ~/code


mkdir build


cd build

(2)运行 cmake 和 make:

cmake ..


make

编译完成后,可执行文件 test 会生成在 build 目录中
(3)运行程序

./test

(4)清理
删除 build 目录

rm -rf ~/code/build

四、talk程序的运用&Linux进程间通信程序的编写

使用talk程序和其他用户交流

首先我们通过who指令查询,可以看到当前已经登录用户信息和终端
在这里插入图片描述

然后输入talk指令连接对应用户进行通信

talk username pts/

在这里插入图片描述

g-iqeL2aNl-1744558582735)
然后等待对方用户连接

上方是我发的信息,下方是对面发的信息
在这里插入图片描述
S-1744558582735)
但是当我们尝试在talk程序下输入中文进行交流时,会出现中文乱码。所以接下来我们尝试自己编写一个c语言程序,实现Linux进程之间的通信。

用c语言写一个linux进程之间通信(聊天)的简单程序

服务器端程序socket_server.c编写

通过nano socket_server.c 新建服务器端程序文件,并进行如下代码编写。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#define PORT 8080#define BUFFER_SIZE 1024
void *handle_client(void *arg) {

 int client_socket = *((int *)arg);    
 char buffer[BUFFER_SIZE];    
 int bytes_read;        
 while (1) {        
 bytes_read = read(client_socket, buffer, BUFFER_SIZE);      
 if (bytes_read <= 0) {         
 break;        }       
 buffer[bytes_read] = '\0';       
 printf("Received: %s", buffer);       
 printf("Enter reply (or 'exit' to quit): ");   
 fgets(buffer, BUFFER_SIZE, stdin);         
 if (strncmp(buffer, "exit", 4) == 0) {     
 write(client_socket, "Server exiting...", 17);         
 break;      
 }           
 write(client_socket, buffer, strlen(buffer));   
 }
 close(client_socket);   
 pthread_exit(NULL);}int main() {  
 int server_fd, client_socket;   
 struct sockaddr_in address;   
 int opt = 1;   
 int addrlen = sizeof(address);  
 pthread_t thread_id;        // 创建socket文件描述符  
 if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {    
 perror("socket failed");      
 exit(EXIT_FAILURE);  
 }        // 设置socket选项    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, 
sizeof(opt))) {        
perror("setsockopt");     
exit(EXIT_FAILURE);
 }       
 address.sin_family = AF_INET;  
 address.sin_addr.s_addr = INADDR_ANY;   
 address.sin_port = htons(PORT);        // 绑定socket到端口   
 if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {        perror("bind failed");      
 exit(EXIT_FAILURE);   
 }        // 开始监听    
 if (listen(server_fd, 3) < 0) {       
 perror("listen");      
 exit(EXIT_FAILURE);    
 }       
 printf("Server started on port %d. Waiting for connections...\n", PORT);      
 while (1) {      
 // 接受新连接


 if ((client_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) 
{        
perror("accept");            
continue;     
}              
printf("New connection from %s\n", inet_ntoa(address.sin_addr));                // 为每个客户端创建新线程       
if (pthread_create(&thread_id, NULL, handle_client, (void *)&client_socket) < 0) {            perror("could not create thread");           
continue;     
}                // 分离线程,使其结束后自动释放资源     
pthread_detach(thread_id);   
}       
close(server_fd);  
return 0;
}


客户端程序socket_client.c编写

通过nano socket_client.c 新建客户端代码文件,并进行如下代码编写

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
​
#define BUFFER_SIZE 1024
​
void *receive_messages(void *arg) {
    int sock = *((int *)arg);
    char buffer[BUFFER_SIZE];
    int bytes_read;
    
    while (1) {
        bytes_read = read(sock, buffer, BUFFER_SIZE);
        if (bytes_read <= 0) {
            printf("Server disconnected\n");
            exit(EXIT_SUCCESS);
        }
         buffer[bytes_read] = '\0';     
         printf("\nReceived: %s", buffer);    
         printf("Enter message (or 'exit' to quit): ");     
         fflush(stdout);  
         }      
         return NULL;}int main(int argc, char const *argv[]) { 
         if (argc != 2) {    
         printf("Usage: %s <server_ip>\n", argv[0]);    
         exit(EXIT_FAILURE);  
         }    
         int sock = 0;    
         struct sockaddr_in serv_addr;   
         char buffer[BUFFER_SIZE] = {0};  
         pthread_t thread_id;        // 创建socket  
         if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {   
         perror("socket creation error");

   exit(EXIT_FAILURE);   
   }        
   serv_addr.sin_family = AF_INET;   
   serv_addr.sin_port = htons(8080);        // 将IP地址从字符串转换为二进制形式   
   if (inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0) {   
   perror("invalid address");    
   exit(EXIT_FAILURE);   
   }        // 连接服务器   
   if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {        perror("connection failed");     
   exit(EXIT_FAILURE);  
   }        
   printf("Connected to server at %s\n", argv[1]);        // 创建接收消息的线程    
   if (pthread_create(&thread_id, NULL, receive_messages, (void *)&sock) < 0) {


  perror("could not create thread");      
  exit(EXIT_FAILURE);  
  }        // 主线程处理发送消息    
  printf("Enter message (or 'exit' to quit): ");    
  while (fgets(buffer, BUFFER_SIZE, stdin)) {   
  if (strncmp(buffer, "exit", 4) == 0) {  
  write(sock, "Client exiting...", 17);    
  break;     
  }                
  write(sock, buffer, strlen(buffer));    
  printf("Enter message (or 'exit' to quit): ");  
  }        
  close(sock);  
  return 0;
  }



程序编译与使用

在服务器和客户端机器上分别编译:


# 服务器端gcc socket_server.c -o server -lpthread
# 客户端gcc socket_client.c -o client -lpthread



接下来我们进行通讯尝试:
在服务器机器上启动服务器程序:

./server

在客户端机器上启动客户端程序,指定服务器IP地址:

./client <服务器IP地址>


网站公告

今日签到

点亮在社区的每一天
去签到