Socket 编程之 epoll 源码分析学习笔记

本文基于 Linux 6.9 内核源码进行分析。 几个数据结构 eventpoll这是 epoll 的主要数据结构,它用于存储 epoll 的相关信息,包括等待队列、就绪队列、红黑树等。 struct eventpoll { wait_queue_head_t wq; // epoll 的等待队列:用于存储等待的进程/线程,指向等待队列头 wait_queue_head_t poll_wait;// 这个 poll_wait 等待队列只有在 epoll 嵌套的情况下才会用到 struct list_head rdllist; // 就绪队列:用于存储就绪的 fd,指向就绪队列头 struct rb_root_cached rbr; // 红黑树:用于存储所有的 fd,指向红黑树根节点 struct wakeup_source *ws; // 一个唤醒源,用于唤醒进程 }; epitemepitem 的作用是将 fd、就绪队列、红黑树节点等信息封装在一起。 struct epitem { union { struct rb_node rbn; // 红黑树节点,用于存储 fd,指向红黑树节点 struct rcu_head rcu; // 用于释放 epitem }; struct list_head rdllink; // 就绪队列节点,用于存储就绪的 fd,指向就绪队列节点 struct eventpoll *ep; // 指向 eventpoll struct epoll_filefd ffd; // epoll 文件描述符 struct wakeup_source *ws; // 一个唤醒源,用于唤醒进程 struct epoll_event event; // 监听的事件 }; ep_pqueue给 poll 队列封装的结构体,用于存储 poll_table 和 epitem。 ...

2024年06月30日 · 9 分钟 · Cassius0924

Windows Socket API 和 Linux Socket API

本文章主要介绍 Windows 下和 Linux 下的 Socket 编程区别,即 Windows Socket API 和 Linux Socket API 的区别。 头文件Windows 环境下的 Socket 编程需要以下头文件: <WinSock2.h> <WS2tcpip.h> 笔记 如果使用 MSVC 编译器,那么还需要使用预处理指令 #pragma comment(lib, "Ws2_32.lib") 来链接 Ws2_32.lib 库。 ...

2024年06月16日 · 2 分钟 · Cassius0924

Linux Boost.Python3 安装以及 CMake 配置指南

下载Boost前往Boost官网下载源码压缩包。 或通过 wget 下载 1.83 版本: wget https://boostorg.jfrog.io/artifactory/main/release/1.83.0/source/boost_1_83_0.7z 下载完毕后,解压 7z 压缩包 7z x boost_1_83_0.7z 编译安装cd boost_1_83_0 ./bootstrap.sh --with-python=/root/.virtualenvs/ETRS/bin/python3 --with-python-version=3.8 --with-libraries=all --with-python 的路径可以通过 which python3 查看。 --with-python-version 的版本号可以通过 python3 --version 查看,注意这里需要填成 3.x 格式 ,而不是 3.y.z,省略最后的版本号。 运行完以上命令后,需要修改 project-config 配置文件。 vim project-config.jam 修改第 21行,在双引号里添加两个路径,分别是当前 Python 版本的 include 路径和 lib 路径。 Python 的 include 路径和 lib 路径可以通过下面的 Python 代码查看: import sysconfig sysconfig.get_path('include') # 查看 include 路径 sysconfig.get_path('stdlib') # 查看 lib 路径 开始编译: ...

2024年06月16日 · 1 分钟 · Cassius0924

Linux 初探之旅(二)——文件与文件夹的读写

在上一篇文章中,我们学习了Linux中的文件浏览,知道了如何在Linux文件系统中定位文件。本篇文章中,我们将继续深入学习Linux中的文件及目录的读写操作。 读取文件cat 命令:读取文件全部内容要读取一个文件的内容,可以使用cat命令,语法为: cat 文件名 这会将文件的全部内容输出到终端。当文件比较大时,这样的输出会刷屏,不太方便查看。 head 和 tail 命令:显示部分内容Linux提供了head和tail命令来显示部分内容: head - 显示开头部分内容 tail - 显示结尾部分内容 head和tail可以指定显示的行数,例如: head -n 3 文件名 # 显示前3行 tail -n 5 文件名 # 显示后5行 less 命令:分页显示less命令可以分页方式显示文件内容,可以上下翻阅,是文件查看的首选工具。 less可以用方向键上下翻页,也支持各种快捷键,推荐大家阅读less的帮助文档。 写入文件echo 命令:输出到文件使用echo命令可以向文件写入内容,语法为: echo "要写入的内容" > 文件名 这会覆盖文件原有内容。如果要附加内容,使用两个大于号: echo "新增内容" >> 文件名 文本编辑器:vim对文件进行复杂编辑可以使用文本编辑器,Linux中的常用文本编辑器有vi、emacs、vim和nano等。这里简单介绍vim的使用。 使用vim 文件名可以打开vim编辑器。vim有三种模式,分别是命令模式、插入模式和底线命令模式。 命令模式:用于导航文件,可以进行复制、粘贴、删除等操作。 插入模式:用于输入文本,可以使用键盘输入文本。 底线命令模式:用于执行命令,例如保存文件、退出vim等。 初学者可以先了解以下几个快捷键: i - 进入插入模式 ESC - 从插入模式回到命令模式 :w - 保存文件 :q - 退出vim vim非常强大,建议大家自己练习熟悉其操作。 删除文件和目录rm 命令:删除文件删除文件使用rm命令: rm 文件名 rm -r 命令:删除目录如果要删除目录,需要添加-r参数: rm -r 目录名 这会递归删除目录及其中的所有内容,需要小心使用。 复制和移动文件 复制使用cp命令,添加-r参数可以复制目录 ...

2024年06月16日 · 1 分钟 · Cassius0924

Linux 初探之旅(三)——重定向、标准输入输出和管道

标准输入输出我们先从Linux最基础的交互来讲起,我们究竟是如何和Linux系统内核进行交互的?换句话说,如何通过在按下键盘,就能让系统实现对应的操作的? 这一切都离不开它,终端——用户与Linux建立起联系的桥梁。 当我们在终端上输入命令的时候,直到我们未按下回车键之前,我们输入的所有内容都储存在终端的缓冲区(Buffer)里。此时我们输入的内容不会被系统所读到,只有在我们按下回车键后,缓冲区里的内容才会被发往 stdin (Standrad input 标准输入),stdin 是 Linux 内核和用户交互的通道。 接着,Shell 会介入,它会将 stdin 收到的内容翻译成操作并执行,Shell 译为壳层,与 Kernel(内核)相对应。Shell在外,Kernel在内。例如我们输入ls,那么 Shell 就会找到 ls 这条命令对应的二进制文件并执行。 执行完命令后,Shell 会将获取到的结果发送到另一条与 stdin 相对应的通道中,即 stdout(Standard output 标准输出)。终端会不间断地从 stdout 里读取内容,然后打印到屏幕上,即我们在终端中看到的输出。 总的来说,用户的输入的内容会发往 stdin 并被 Shell 读取,Shell 将找到内容所对应的二进制文件并执行,执行完后 Shell 会将结果发往 stdout 中,及时的显示在屏幕上。这就是一次与 Linux 交互的过程。 我们总说,在 Linux 中一切皆为文件,那么 stdin 和 stdout 也不例外,它们也是系统的两个文件。除了 stdin 和 stdout 之外,还有第三条通道 stderr(Standard error 标准错误)。stderr 和 stdout 一样,它们都是用于存储执行结果的地方,区别在于,Shell 执行完命令后,会将正常的结果发往 stdout 里,将错误的结果发往 stderr 里。同样地,stderr 也会被终端所读取,最后显示在屏幕上。 输出重定向理解了标准输入输出后,我们能弄懂重定向的原理了,实际上就是 Shell 执行完命令后不把输出结果存放在 stdout 或 stderr 。而是存放到另一个文件当中。 ...

2024年06月16日 · 1 分钟 · Cassius0924

Linux 批量修改文件名指南

使用 bash 脚本,先创建一个 .sh 结尾的脚本: vim rename.sh 以下是示例 bash 脚本内容,作用是将 /path/to/dir 目录下所有包含冒号:的文件名,将冒号替换为减号。 # !/bin/bash find /path/to/dir -type f -name '*:*' -exec bash -c 'mv "$0" "${0//:/-}"' {} \; 代码解释使用find查找需要更改的文件find /path/to/dir -type f -name '*:*' /path/to/dir 应该替换为包含你要修改文件名的文件夹的实际路径。 -type f 表示只查找普通文件,而不包括目录。 -name '*:*' 是一个查找条件,用于匹配包含冒号的文件名。 使用mv和bash执行文件名更改一旦找到需要更改的文件,可以使用mv命令结合bash来执行文件名更改操作。 find /path/to/dir -type f -name '*:*' -exec bash -c 'mv "$0" "${0//:/-}"' {} \; 这个命令中的 -exec 标志用于在find查找到的每个文件上执行指定的命令。bash -c之后的部分将执行文件名更改操作。 mv "$0" "${0//:/-}" 使用mv命令将文件名中的冒号替换为减号。${0//:/-} 部分是一个bash子shell,其中的${0}表示当前文件名,//后跟着:和-是用来替换的正则表达式。

2024年06月16日 · 1 分钟 · Cassius0924

Ubuntu Neovim 安装和配置指南

安装不建议使用apt安装,因为apt安装的版本总是不是最新版。一些neovim插件依赖于高版本的neovim,因此使用apt安装可能会导致一些插件无法正常使用。 下面介绍安装最新版neovim的方法。 下载安装压缩包: wget https://github.com/neovim/neovim/releases/latest/download/nvim-linux64.tar.gz 安装: tar xzvf nvim-linux64.tar.gz cp ./nvim-linux64/bin/nvim /usr/bin/ 测试: nvim -v nvim配置核心配置配置 nvim 需要先创建配置文件的文件夹。 cd ~ mkdir -r .config/nvim cd .config/nvim nvim 使用 lua 语言作为配置文件语言,新建 init.lua,该文件是 nvim 的配置的入口。 touch init.lua 模块化配置nvim 支持模块化配置,所以可以在 nvim 文件夹下创建多个配置模块: mkdir -r lua/core cd lua/core core 文件夹存放 nvim 的核心配置,例如 nvim 基础配置(options.lua)和快捷键配置(keymaps): touch options.lua keymaps.lua 此时,neovim 的配置文件结构如下所示: ~ `--.config `-- nvim |-- init.lua |-- lua | |-- core | | |-- keymaps.lua | | `-- options.lua | `-- plugins | `-- plugins-setup.lua `-- plugin `-- packer_compiled.lua 回到 init.lua 文件,在 init.lua 中调用刚刚新建的两个模块: ...

2024年06月16日 · 1 分钟 · Cassius0924

Jetson (Ubuntu Arm64) 安装 Bazel

简介本文旨在帮助用户在 Jetson 上的 Ubuntu Arm64 系统上安装 Bazel。Bazel 是一个开源的构建工具,它专注于构建和测试大型软件项目,并且被广泛应用于机器学习和深度学习领域。通过使用 Bazel,您可以更高效地管理和构建您的项目。 步骤 1:安装OpenJDK在开始安装 Bazel 之前,我们需要安装 OpenJDK。在终端中执行以下命令: sudo add-apt-repository ppa:webupd8team/java sudo apt-get update sudo apt-get install openjdk-11-jdk 步骤 2:下载 Bazel 安装包在安装 OpenJDK 之后,我们需要下载 Bazel 的安装包。在终端中执行以下命令: wget https://github.com/bazelbuild/bazel/releases/download/6.2.1/bazel-6.2.1-dist.zip 或者,您也可以从 Bazel 的 Github 仓库下载最新版本的安装包。(必须下载dist.zip文件) 步骤 3:安装 Bazel下载完成后,我们可以使用以下命令来安装 Bazel: unzip bazel-6.2.1-dist.zip -d bazel-6.2.1 bash./compile.sh sudo cp output/bazel /usr/local/bin 步骤 4:验证安装安装完成后,我们可以验证 Bazel 是否成功安装。在终端中执行以下命令: bazel version 如果一切正常,您应该能够看到如下输出:

2023年06月14日 · 1 分钟 · Cassius0924

Ubuntu 安装 Protobuf 指南

Protobuf(Protocol Buffers)是一种轻量级的数据交换格式,常用于高效地序列化结构化数据。本指南将介绍如何在 Ubuntu 上安装 Protobuf。 步骤 1:更新系统在安装 Protobuf 之前,我们首先需要确保系统已经更新到最新版本。打开终端并执行以下命令: sudo apt update sudo apt upgrade 这将更新系统的软件包并安装最新的安全补丁。 步骤 2:安装编译工具和依赖项在安装 Protobuf 之前,我们需要安装一些编译工具和依赖项。执行以下命令来安装它们: sudo apt install build-essential autoconf libtool 这些工具和依赖项将帮助我们编译和构建 Protobuf。 步骤 3:下载和编译 Protobuf 首先,我们需要下载 Protobuf 的源代码。这里选择下载v3.20.3版本的Protobuf源码压缩包。(必须下载-all压缩包) 解压压缩包 tar -zxvf protobuf-all-3.20.3.tar.gz 这将克隆 Protobuf 的源代码到当前目录。 进入克隆下来的 Protobuf 目录: cd protobuf-all-3.20.3 在源代码目录中,运行以下命令来生成配置文件和构建系统: ./autogen.sh 接下来,我们需要运行 configure 脚本来配置编译选项。可以使用以下命令进行配置: ./configure 配置完成后,我们可以使用以下命令编译和安装 Protobuf: sudo make sudo make check #这一步可能会报错,解决方法见下文 sudo make install sudo ldconfig 编译过程可能需要一些时间,请耐心等待。 步骤 4:验证安装安装完成后,我们可以验证 Protobuf 是否成功安装。执行以下命令来检查 Protobuf 的版本信息: ...

2023年06月12日 · 1 分钟 · Cassius0924

解决 Open3D 同时链接其他库时的 Undefined Reference 错误

当你的 Open3D 项目同时使用了 OpenCV 或 Protobuf 等其他库时,在链接库时可能会出现 Undefined Reference 的错误。这是因为 Open3D 默认使用的 C++ ABI 版本与其他库不一致导致的。 为了解决这个问题,可以在重新编译安装 Open3D 时打开 -DGLIBCXX_USE_CXX11_ABI=ON 选项,即使用 C++11 ABI 版本。以下是具体的步骤: 解决方法找到 Open3D 源码cd open3d 找不到请在 Github 上重新下载。 重新编译安装 Open3D进入 Open3D 的源代码目录的 build 子目录进行编译安装。 cd build 在 build 子目录中执行 CMake 命令生成 Makefile。在命令行中添加 -DGLIBCXX_USE_CXX11_ABI=ON 选项。 cmake .. -DBUILD_SHARED_LIBS=ON -DGLIBCXX_USE_CXX11_ABI=ON -DCMAKE_BUILD_TYPE=Release 最后,执行 make 命令编译并安装 Open3D。 make -j6 sudo make install 使用 Open3D重新编译安装后的 Open3D 就能够正常链接其他库了。

2023年06月09日 · 1 分钟 · Cassius0924