2024-08-23

在Linux系统中,管道是一种常见的进程间通信(IPC)机制,它可以把一个进程的输出作为另一个进程的输入。管道主要有两种类型:无名管道和命名管道。

无名管道是单向的,只能在有亲缘关系的进程间使用。它通过调用pipe()函数创建,该函数会填充一个整型数组包含两个元素,其中fd[0]用于读取,而fd[1]用于写入。

以下是一个使用无名管道的示例代码:




#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
 
int main() {
    int fd[2];
    pid_t pid;
    char buf;
 
    if (pipe(fd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }
 
    if ((pid = fork()) == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    }
 
    if (pid == 0) { 
        /* 子进程 */
        close(fd[1]); // 关闭写端
        while (read(fd[0], &buf, 1) > 0) {
            write(STDOUT_FILENO, &buf, 1);
        }
        close(fd[0]);
        _exit(EXIT_SUCCESS);
    } else {
        /* 父进程 */
        close(fd[0]); // 关闭读端
        write(fd[1], "Hello, World!", 14);
        close(fd[1]);
        wait(NULL);
    }
 
    return 0;
}

在这个例子中,父进程创建了一个管道,然后创建了一个子进程。父进程关闭了读端,通过写端发送数据“Hello, World!”,子进程关闭了写端,通过读端读取数据并打印。

命名管道(FIFO)允许无亲缘关系进程间通信。它通过mkfifo()函数创建一个文件,然后像读写文件一样对它进行操作。

以下是一个使用命名管道的示例代码:




#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
 
#define FIFO_NAME "/tmp/my_fifo"
 
int main() {
    char buf_r;
    int fd;
 
    // 创建命名管道
    if (mkfifo(FIFO_NAME, 0666) < 0) {
        perror("mkfifo");
        exit(1);
    }
 
    // 打开管道进行读取
    fd = open(FIFO_NAME, O_RDONLY | O_NONBLOCK, 0);
    if (fd < 0) {
        perror("open");
        exit(1);
    }
 
    while (1) {
        int n = read(fd, &buf_r, 1);
        if (n > 0) {
            printf("Received: %c\n", buf_r);
        }
    }
 
    close(fd);
    unlink(FIFO_NAME);
 
    return 0;
}

在这个例子中,首先创建了一个命名管道,然后打开它进行非阻塞读取。这样,即使当前没有数据可读,读取操作也不会阻塞,可以继续执行其他任务。

2024-08-23

在Linux中,tail 命令用于输出文件的最后几行。如果你想实时监控文件的更新,可以使用 tail -f 命令。

tail -f 命令的功能是:输出文件的最后几行,并在文件增长时输出增加的数据。-f 选项是 "follow" 的简写,意思是持续监控文件的更新。

例如,你可以使用 tail -f 命令来实时查看系统日志文件:




tail -f /var/log/syslog

如果你只是想查看文件的最后几行,那么使用 tail 命令就可以了:




tail /var/log/syslog

注意:tailf 并不是一个标准的 tail 命令的用法。可能你是想输入 tail -f。如果你的意图是监控文件的更新,那么使用 tail -f 是正确的命令。

2024-08-23

软硬链接和动态/静态库在Linux系统中都是常用的概念,下面是简要介绍和示例:

  1. 软链接(Symbolic Link):

    创建软链接的命令是ln -s,它创建的是一个符号链接,类似于Windows系统中的快捷方式。




ln -s /path/to/original /path/to/link
  1. 硬链接(Hard Link):

    创建硬链接的命令是ln,没有 -s 参数。硬链接会创建一个新的文件名指向同一个文件数据。




ln /path/to/original /path/to/link
  1. 动态库(Dynamic Library):

    在Linux中,动态库通常以.so(Shared Object)结尾,例如libexample.so。在编译时,只有在运行时才会将程序与动态库链接。

  2. 静态库(Static Library):

    静态库以.a结尾,例如libexample.a。在编译时,静态库的内容会被直接复制到程序中,程序运行时不再依赖静态库。

创建动态库的例子:




// example.c
int add(int a, int b) {
    return a + b;
}

编译为动态库:




gcc -shared -o libexample.so example.c

创建静态库的例子:




ar rcs libexample.a example.o

在这里,example.o 是通过 gcc -c example.cexample.c 源文件生成的目标文件。

2024-08-23

在Linux系统中,free命令用于显示系统内存的使用情况。free命令会报告总计的、已用的、空闲的物理内存和交换内存,还会报告共享内存和缓冲区。

free命令输出中的Mem行(对于总计的内存)和-/+ buffers/cache行(对于可用的内存),有时会造成理解上的混淆。

总计的内存(Mem)= 物理内存总量(total)

已使用的内存(used)= 总内存量 - 空闲内存量(free)

空闲的内存(free)= 缓冲区和缓存(buffers + cached)

可用的内存(available)是从应用程序的角度来看的可以被用来进行新分配的内存量,它考虑了内核的预留和当前的需求。

可用内存(available)≈ 空闲的内存(free) + 缓冲区被释放的内存(buffers) + 缓存被释放的内存(cached)

注意,这里的“释放”意味着内存被交换出来,可以立即被用于其他用途。

在命令行中,你可以通过以下命令来获取freeavailable内存的信息:




free -h

这将以易读的格式(如GB、MB)显示内存信息。-h参数是可选的,但它会让输出更易于阅读。

如果你想要获取可以用Python脚本来获取这些信息,你可以使用psutil库,这是一个跨平台的进程和系统实用工具模块。




import psutil
 
mem = psutil.virtual_memory()
 
print(f"Total: {mem.total / 1024 ** 2} MB")
print(f"Available: {mem.available / 1024 ** 2} MB")
print(f"Used: {(mem.total - mem.available) / 1024 ** 2} MB")

这段Python代码会输出总计的内存、可用的内存和已使用的内存,所有的值都是以MB为单位。

2024-08-23



#!/bin/bash
 
# 创建云盘
create_volume() {
    echo "创建云盘中..."
    volume_id=$(huaweicloud ecs CreateVolume --availability-zone "az1.example.com" --size 100 --volume-type SATA --profile "default" | grep "| id" | awk '{print $4}')
    echo "云盘创建成功,云盘ID: ${volume_id}"
}
 
# 等待云盘就绪
wait_for_volume_status() {
    echo "等待云盘就绪中..."
    huaweicloud ecs WaitForVolumeStatus --volume $1 --status "available" --profile "default"
    echo "云盘就绪"
}
 
# 挂载云盘
attach_volume() {
    echo "挂载云盘中..."
    device_name=$(huaweicloud ecs AttachVolume --volume $1 --instance-id "i-xxxxx" --device "/dev/vdc" --profile "default" | grep "device" | awk '{print $4}')
    echo "云盘挂载成功,设备名: ${device_name}"
}
 
# 初始化云盘
initialize_volume() {
    echo "初始化云盘中..."
    mkfs.ext4 /dev/vdc
    echo "云盘初始化成功"
}
 
# 挂载点目录
mount_point="/mnt/cloud_disk"
 
# 主程序
main() {
    create_volume
    volume_id=$(echo ${volume_id##*id = })
    wait_for_volume_status ${volume_id}
    attach_volume ${volume_id}
    mkdir -p ${mount_point}
    mount /dev/vdc ${mount_point}
    echo "${mount_point} /dev/vdc ext4 defaults 0 0" >> /etc/fstab
}
 
main

这段代码首先定义了创建云盘、等待云盘就绪、挂载云盘和初始化云盘的函数。主程序中依次调用这些函数来完成一个完整的流程。这个流程展示了如何在Linux环境下管理云盘,包括创建、挂载和格式化。

2024-08-23

在Linux上安装CMake通常可以通过包管理器来完成。以下是一些常见Linux发行版的安装命令:

对于基于Debian的系统(如Ubuntu):




sudo apt-update
sudo apt-get install cmake

对于基于RedHat的系统(如Fedora或CentOS):




sudo yum install cmake

对于Fedora(使用dnf代替yum):




sudo dnf install cmake

对于Arch Linux:




sudo pacman -S cmake

对于openSUSE:




sudo zypper install cmake

安装完成后,可以通过运行cmake --version来检查CMake是否正确安装。

2024-08-23

为了交叉编译适用于Linux aarch64平台的Qt5,你需要设置合适的交叉编译工具链并配置Qt源码编译系统。以下是一个基本的步骤概述:

  1. 安装交叉编译工具链,例如Linaro的Aarch64编译器。
  2. 下载Qt5的源码。
  3. 配置源码以进行交叉编译。
  4. 编译并安装Qt5。

以下是具体的命令示例:




# 安装交叉编译工具链
sudo apt-get install g++-aarch64-linux-gnu
 
# 下载Qt5源码
wget http://download.qt.io/official_releases/qt/5.15/5.15.2/single/qt-everywhere-src-5.15.2.tar.xz
tar xf qt-everywhere-src-5.15.2.tar.xz
cd qt-everywhere-src-5.15.2
 
# 配置Qt编译环境
./configure -prefix /usr/aarch64-linux-gnu -opensource -confirm-license -release -make libs -xplatform linux-aarch64-gnu-g++ -optimized-qmake -pch -qt-libjpeg -qt-libpng -qt-zlib -nomake examples -nomake tests
 
# 编译并安装Qt
make -j$(nproc)
sudo make install

请注意,你需要根据你的目标平台和Qt版本调整交叉编译选项。上面的示例使用了Linaro的Aarch64交叉编译器,并假设你的目标平台是基于GNU的系统。如果你的目标平台有不同的ABI,你可能需要使用相应的交叉编译工具链和调整xplatform参数。

2024-08-23

在 Linux 中,可以使用 >>> 操作符来将命令的输出重定向到文件中。> 用于将输出重定向到文件,如果文件已存在则会覆盖它。而 >> 会将输出追加到文件的末尾,如果文件不存在则会创建它。

同时,可以使用 tee 命令将输出同时发送到文件和标准输出(屏幕)。

例子:

ls 命令的输出重定向到 list.txt 文件中,覆盖文件内容:




ls > list.txt

ls 命令的输出追加到 list.txt 文件的末尾:




ls >> list.txt

ls 命令的输出同时重定向到 list.txt 文件和屏幕:




ls | tee list.txt

ls 命令的输出同时追加到 list.txt 文件和屏幕:




ls | tee -a list.txt
2024-08-23

在Linux中实现线程互斥,通常使用互斥锁(mutex)。互斥锁提供了一种简单的方法来保证在任何时刻只有一个线程能够访问某个资源或代码段。

以下是使用互斥锁的基本步骤:

  1. 定义一个互斥锁。
  2. 初始化互斥锁。
  3. 加锁,在访问共享资源或代码段之前。
  4. 解锁,在完成访问共享资源或代码段之后。

下面是一个简单的例子,展示了如何在Linux中使用互斥锁:




#include <pthread.h>
#include <stdio.h>
 
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 定义并初始化互斥锁
 
void* thread_function(void* arg) {
    pthread_mutex_lock(&mutex); // 加锁
    // 临界区 - 访问共享资源
    printf("Thread ID: %lu\n", pthread_self());
    // 临界区结束
    pthread_mutex_unlock(&mutex); // 解锁
    return NULL;
}
 
int main() {
    pthread_t thread1, thread2;
 
    // 创建线程
    pthread_create(&thread1, NULL, &thread_function, NULL);
    pthread_create(&thread2, NULL, &thread_function, NULL);
 
    // 等待线程完成
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
 
    return 0;
}

在这个例子中,thread_function 是每个线程要执行的函数,它包含了一个临界区(通过 printf 输出线程ID)。互斥锁 mutex 被用来确保同一时刻只有一个线程可以执行临界区中的代码。

请注意,在实际编程中,互斥锁的加锁和解锁应当放在 trycatch 块中,以确保即使在发生异常的情况下也能正确解锁,防止死锁的发生。

2024-08-23

在Linux系统中,可以使用iptables来设置特定端口的IP白名单。以下是一个示例,展示了如何为端口22(通常是SSH服务使用的端口)设置IP白名单。

首先,你需要确定你要允许的IP地址。然后,使用以下命令添加规则:




# 允许白名单中的IP地址访问端口22
iptables -A INPUT -p tcp --dport 22 -s 白名单IP地址 -j ACCEPT
 
# 禁止所有其他IP地址访问端口22
iptables -A INPUT -p tcp --dport 22 -j DROP

白名单IP地址替换为你希望允许访问端口22的具体IP地址。如果你有多个IP地址需要添加,你可以重复这个命令,每个IP地址一次。

请注意,这些规则在重启后不会自动保留。要永久保存这些规则,你需要将它们添加到iptables的配置文件中,这个文件通常是/etc/iptables/rules.v4(路径可能因发行版而异)。

这里是一个示例,展示了如何将规则添加到/etc/iptables/rules.v4文件中:




# 添加允许的规则
echo "iptables -A INPUT -p tcp --dport 22 -s 白名单IP地址 -j ACCEPT" >> /etc/iptables/rules.v4
 
# 添加拒绝的规则
echo "iptables -A INPUT -p tcp --dport 22 -j DROP" >> /etc/iptables/rules.v4

然后,重启iptables服务以应用这些规则:




sudo service iptables restart

或者在不同的Linux发行版中,可能需要使用以下命令:




sudo systemctl restart iptables.service

确保你有足够的权限执行这些操作,通常需要root权限。