0%

定时器 API

1. setitimergetitimer(不建议)

SYNOPSIS
       #include <sys/time.h>

       int getitimer(int which, struct itimerval *curr_value);
       int setitimer(int which, const struct itimerval *restrict new_value,
                     struct itimerval *_Nullable restrict old_value);

which 参数指定创建的定时器的类型

  • 可以是真实时间,到期的信号是 SIGALARM。
  • 可以是用户 CPU 时间(进程虚拟时间),到期的信号为 SIGVTALRM。
  • 可以是内核 + 用户 CPU 时间(profiling 定时器),到期的信号是 SIGPROF。

以上三种信号默认行为是终止进程,所以定时器要结合信号处理函数使用。

struct itimerval 参数解释

struct itimerval {
   struct timeval it_interval; /* Interval for periodic timer */
   struct timeval it_value;    /* Time until next expiration */
};

其中 timeval 是带有秒和微秒的结构体,可以参考 10.01 时间类型 tm time_t timeval timespec

情况

项目是由 CMake 构建的动态库,用 CPack 我们打包得到了一个 deb 包版本和一个 tar.gz 的压缩包版本。前者安装之后 demo 能够正常编译运行,但是在换用压缩包安装共享库后编译 demo 则出现了找不到库的错误(这里讨论的是非标准路径的情况,即安装路径不在 //usr/usr/local 下)。

测试 demo 是用 Makefile 写的,设置了 INCLUDE 环境变量为要包含的头文件路径,并且新增了 /etc/ld.so.conf.d/xxx.conf 和重做了 ldconfig 的 cache。但是 gcc 还是无法识别这个库。

Tip

这是因为 ldconfig 只是管理一个库在运行时可以去哪些路径搜索,静态链接的时候链接器不会去看这个配置。INCLUDE 环境变量可能是我记错了,我现在没有找到什么工具是认识这个环境变量的。CMake 认识的环境变量可以参考链接 https://cmake.org/cmake/help/latest/manual/cmake-env-variables.7.html 。Make 也认识一些环境变量,但是 INCLUDE 不在其列。

我想要真正把共享库安装在系统里面,所以不想在 Makefile 中手动去加头文件包含路径和库路径(那样的话需要修改每个 Makefile)。

解决 gcc 找不到头文件的问题

设置 INCLUDE 环境变量,但是 gcc 不认。如果认的话理应输出 ignoring nonexistent directory "/aaaa"

操作起来感觉 apt 和 dpkg 在安装和卸载软件上是可以混用的,其一安装的包可以由另外一者去卸载。

安装软件(-i | --install

dpkg -i localpackage.deb

经过测试,不必像 apt 一样需要加上 ./ 前缀以安装本地的软件包。

卸载软件(-r | --remove

dpkg -r packagename

必须要使用包名才能卸载,使用 dpkg -r localpackage.deb 这样的文件路径是无效的。查看报名的方式是:

狼蛛 M75 在 618 首发会送 80 颗鲸海轴,把鲸海轴的价格打下来了,全新在咸鱼上是 75~80 元。而且是刚好 80 颗!和我的 V75K 的按键数一样,所以头脑一热就入了。我前几天也把极光冰淇淋轴和静音轴都出了:静音轴体用着还是有点憋屈,而冰淇淋轴对于我来说始发压力(30 gf)太轻了,在滑键的时候会发出声音,我不喜欢。

🤔 是不是对我来说选择始发压力 35 gf 以上的轴体会比较合适呢?

外观:轴体本身是蓝色的,没有导光柱,和极光冰淇淋其实蛮像的,也就懒得拍了。

手感:按压力度上鲸海轴比较适中,参数和红轴很相近,但是它有一种液压感,快速重复按压会觉得压力很大(比如连续按 backspace),但是慢慢打字又觉得压力比较合适。和我之前使用的阿尼亚轴比起来肯定是要费力一些。因为有防尘壁,轴体实装后按键的稳定性相当不错。

声音:很不错,比极光冰淇淋好很多。声音也是比较闷的,音量上比阿尼亚小一点。

TL;DR

如果想要写一些 traits,而且涉及到了函数和变量(而不是类型),则需要同时加上 __device____host__ 以确保它在 device 侧和 host 侧都可见。否则会因为 SFINAE 不报错(实际上可能是在 device 侧找不到函数或变量),而且不知道为什么结果不对。

描述

项目用的语言标准是 C++17,atomicAdd 是 CUDA 中的一族函数,能对支持类型进行原子操作,其参数为一个地址和一个值,我想要判断 atomicAdd 是否有某个基本数据类型对应的重载版本。

template <typename T, typename U = std::decay_t<T>>
__device__ __host__ auto atomicAddTest(T&&)
    -> std::void_t<decltype(atomicAdd((U*)(nullptr), std::declval<U>()))>;

__device__ __host__ auto atomicAddTest(...) -> int;

template <typename T>
__device__ __host__ static inline constexpr auto atomicAddable =
    std::is_same_v<decltype(atomicAddTest(std::declval<T>())), void>;

static_assert(atomicAddable<float>);
static_assert(atomicAddable<unsigned>);

看起来很正常对不对?但是如果想要同时在 host 侧和 device 侧来使用 atomicAddable 变量,但是又忘记给这些函数加 __device__ __host__,就会有 calling device function from host 的错误,然后因为 SFINAE 不报错,下面的程序实际使用时总是走了不一样的分支,半天不知道原因在哪里!后来加了 static_assert,同时暂时性地将 SFINAE 保护的部分放到函数体里面去,才通过 LSP 了解到具体的出错原因。

接下来编译又出现一个问题:

极光冰淇淋轴是我从咸鱼上买的,本来买完有点后悔,因为我看到了有人出我更想要的蓝莓冰淇淋,而且价格相当好,但是这倒也没什么。比较难受的是:卖家说自己是到手拆,但是我拿到的轴针脚歪歪扭扭的,特别是有一个轴的金色针脚都快从中间一分二了。如果平时都没怎么用过,我都不敢想装货的时候有多暴力。而且这个卖家卖了特别多键设,原来大家的容忍度都这么高吗?

我个人觉得有棉花塞棉花,没有棉花塞卫生纸,不要在罐子中留下空隙,不然即使没有外力压迫,罐子在运输过程中不断摇晃也是可能损伤到针脚的。

吐槽完交易来说体验,我觉得极光冰淇淋有点对不起它拆机 1.4、1.5 元的价格。先看外观图,粉色的是阿尼亚,紫色的是极光冰淇淋,极光冰淇淋的颜值还是很高的,我很喜欢这种圆形防尘壁的设计:

外观是好看的,没什么说的。但是声音不好听。按键感觉也不够顺滑,有的好按有的不好按,和更便宜的阿尼亚轴完全没法比(2024 年 6 月 29 日:听说极光冰淇淋需要自润)。虽然平均压力是 40 gf,但是比 42 gf 为平均压力的阿尼亚轴体感要费力很多,是因为公差比较大吗?

C++ 中两数相除(假设被除数和除数都不是 0),同号则结果为正,异号则结果为负。模除运算则定义为:

If $a~/~b$ is representable in the result type, $(a~/~b)*b + a~\%~b == a$.(来自 https://en.cppreference.com/w/cpp/language/operator_arithmetic

实践起来则是:在被除数不是 0 的情况下,模除运算的结果总是和除数同正负。

昨天晚上合并完新的代码准备提交上去但是 CI 跑不了,有一个单元测试报错。然后照着官方的 git-bisect 文档找问题。这个工具比想象中要好用很多,大部分时间都花在了构建项目上面(每次修改 HEAD 之后都要重新构建才能测试)。半个小时后锁定了问题在一个具体的提交上。

接下来我需要将我的代码和这部分有问题的代码分离。我的分支是 main,远程的分支是 origin/develop,有错误的分支是 origin2/develop。因为 main 合并了一部分 origin2/develop 的代码才导致了错误。分支的结构是这样的:

* --(若干次提交)-- origin/develop  --(若干次提交)-- main
 \                                              / (若干次提交,非线性,想要舍弃掉)
   --- origin2/develop -------------------------

因为我要保证 origin/develop 这个我们的仓库总是 fast-forward 合并,所以我先以这个分支为基准创建新的本地分支。然后将在 main 中(有我的新代码)、不在 next 中(因为我本来就在 next 的位置上)、不在 origin2/develop 中(有错误)的提交重播。

git checkout -b next origin/develop
git cherry-pick main ^next ^origin2/develop

步骤

docker save image:tag | zstd -o image.tar.zst
  • docker save 是将镜像输出到标准输出流,docker save -o 是将输出写入到文件。
  • zstd -o 是将压缩数据写入文件,而 zstd -c 是将压缩的数据输出到标准输出流。

为什么用 zstd 而不是 gzip 来压缩

  1. zstd 在 ubuntu/debian 中有现成的包可以下载,安装非常轻松。
  2. 压缩速度非常快,压缩比可以接受。
  3. 我的使用场景是在服务器之间传输文件,带宽很高,所以不想花太多时间在压缩和解压上。

核心转储

核心转储的产生

有非常多的原因会导致核心转储不发生,最容易出现的是没有用 ulimit 对进程设置核心转储大小上限(默认是 0)。此外,对核心转储路径没有写权限、set-group-ID 或 set-user-ID 程序由非属组 / 主执行、对可执行文件没有读权限等原因都会导致核心转储不发生。

在 Linux 2.4 之后,prctl 函数的 PR_SET_DUMPABLE 操作可以为进程设置 dumpable 标志,如果有这个标志,set-group-ID 或 set-user-ID 程序在非属组 / 主执行时也能核心转储。Linux 2.6.13 之后,/proc/sys/fs/suid_dumpable 为此标志提供系统级的控制,默认值是 0。

Linux 2.6.23 之后,/proc/PID/coredump_filter 能控制对应进程核心转储中可以包含的内存类型。文件的值是 4 位掩码,表示私有匿名映射、私有文件映射、共享匿名映射以及共享文件映射是否受允许,默认值是仅允许匿名映射、不允许文件映射。如今,我的 WSL 内核版本是 5.15.153.1-microsoft-standard-WSL2,该文件中存储的是 00000033

核心转储的路径

可以用 /proc/sys/kernel/core_pattern 查看核心转储文件的存储路径。

系统对一些特殊信号的处理

SIGKILL 和 SIGSTOP 的行为无法被改变,调用 signalsigaction 以图改变其行为总是会返回错误。