0%

Linux定时器

学习《Linux高性能服务器编程》第十一章定时器,里面介绍了各种网络程序中的定时事件,为了印象深刻一些,多动手多实践,所以记下这个笔记。这一篇主要记录Linux中SIGALRM信号触发的定时器。

阅读全文 »

电脑上玩GBA游戏(GBA模拟器)

最近重温了神奇宝贝系列的动画,想到小时候在GBA上玩的口袋妖怪系列游戏,想在电脑上重新玩一下,所以记录一下几个开源的GBA游戏模拟器。

visualboyadvance-m

下载

仓库地址:https://github.com/visualboyadvance-m/visualboyadvance-m

直接去release里面下载

image-20220831230708171

visualboyadvance-m-Win-64bit.zip是打包好的模拟器。

translations.zip是翻译文件,因为原版是英文的,我们想用中文就得下载这个

阅读全文 »

信号

学习《Linux高性能服务器编程》第十章信号,为了印象深刻一些,多动手多实践,所以记下这个笔记。这一篇主要记录Linux中

Linux信号概述、信号集、信号函数和一些疑惑。

阅读全文 »

改变工作目录和根目录

进程有工作目录和根目录。

工作目录:进程在哪个路径下被运行起来哪个路径就是进程的工作目录(Current Woring Directory, CWD)

根目录:就是”/“

工作目录和根目录可以通过/proc/PID/cwd/proc/PID/root进行查看

image-20220821175748810

阅读全文 »

进程间关系

进程组

Linux下每个进程都隶属于一个进程组,因此它们除了PID信息外,还有进程组ID(PGID)。我们可以用如下函数来获取指定进程PGID:

1
2
3
4
#include <sys/types.h>
#include <unistd.h>

pid_t getpgid(pid_t pid);

该函数成功时返回进程pid所属进程组的PGID,失败则返回-1并设置errno

每个进程组都有一个首领进程,其PGIDPID相同。进程组将一直存在,直到其中所有进程都退出,或者加入到其他进程组。下面的函数用于设置PGID

1
int setpgid(pid_t pid, pid_t pgid);

该函数将PIDpid的进程的PGID设置为pgid

如果pidpgid相同,则由pid指定的进程将被设置为进程组首领;

如果pid为0,则表示设置当前进程的PGIDpgid

如果pgid为0,则使用pid作为目标PGID

setpgid函数成功时返回0,失败则返回-1并设置errno.

一个进程只能设置自己或者其子进程PGID。并且,当子进程调用exec系列函数后,我们也不能再在父进程中对它设置PGID

阅读全文 »

UID、EUID、GID和EGID

Linux中id真是太多了进程有pid,然后用户还有UID这种,真是有点绕。

在Linux当中一个进程(程序)拥有四个ID:真实用户UID、有效用户EUID、真实组GID和有效组EGID

这里以真实用户UID和有效用户EUID为例,真实组GID和有效组EGID道理是相同的。

EUID存在的目的是方便资源访问:它使得运行程序的用户拥有该程序的有效用户的权限(太过官方这种说法感觉)。EUID确定进程对某些资源和文件的访问权限。在大多数情况下,进程的UIDEUID是一样的,但是对于一些程序如supasswd这种set-user-id程序,它们有可能是不相同的。对于set-user-id程序而言,程序的EUID会变成程序的所有者UID,也就是说程序执行时,是以程序的所有者身份进行运行的。

阅读全文 »

Linux系统日志rsyslogd

Linux系统日志

Linux上使用rsyslogd守护进程接收用户进程输出的日志和接收内核日志。

用户进程是通过syslogd函数生成系统日志。该函数将日志输出到一个UNIX本地域socket类型(AF_UNIX)的文件/dev/log中,rsyslogd则监听该文件以获取用户进程的输出。

内核日志是如何进行管理的,在这里我们不进行关系。

rsyslogd守护进程在接收到用户进程内核输入的日志后,会把它们输出至某些特定的日志文件。默认情况下,调试信息会保存至/var/log/debug文件,普通信息保存至/var/log/messages文件,内核消息则保存至/var/log/kern.log文件。

不过,日志信息具体如何分发,可以在rsyslogd的配置文件中设置。rsyslogd的主配置文件是/etc/rsyslog.conf,其中主要可以设置的项包括:内核日志输入路径,是否接收UDP日志及其监听端口(默认是514,见/etc/services文件),是否接收TCP日志及其监听端口,日志文件的权限,包含哪些子配置文件(比如 /etc/rsyslog.d/*.conf)。rsyslogd的子配置文件则指定各类日志的目标存储文件。

image-20220818105707879

阅读全文 »

fcntl函数

fcntl函数提供了对文件描述符的各种控制操作。

1
2
3
4
#include <unistd.h>
#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */ );

fd参数是被操作的文件描述符,cmd参数指定执行何种类型的操作。根据操作类型的不同,该函数可能还需要第三个可选参数 argfcntl函数支持的常用操作及其参数如下表所示。

阅读全文 »

tee函数

tee函数在两个管道描述符之间复制数据,也是零拷贝操作。它不消耗数据,因此源文件描述符上的数据仍然可以用于后续操作。

1
2
3
#include <fcntl.h>

ssize_t tee(int fd_in, int fd_out, size_t len, unsigned int flags);

fd_infd_out是文件描述符,但是必须是管道文件描述符

len参数指定移动数据的长度

flags参数则控制数据如何移动,它可以被设置为下表中的某些值的按位或,它的参数其实和splice函数相同。

image-20220816100934412

tee函数成功时返回在两个文件描述符之间复制的数据数量(字节数)。返回0表示没有复制任何数据。tee失败时返回-1并设置errno

阅读全文 »

splice函数

splice用于在两个文件描述符之间移动数据,是零拷贝操作。看了man手册,发现这个splice函数跟pipe管道关系不浅。

image-20220816100155851

1
2
3
#include <fcntl.h>

ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags);

fd_in参数是待输人数据的文件描述符。如果fd_in是一个管道文件描述符,那么 off_in参数必须被设置为NULL。如果fd_in不是一个管道文件描述符(比如 socket),那么off_in表示从输入数据流的何处开始读取数据。此时,若off_in被设置为NULL,则表示从输入数据流的当前偏移位置读入;若off_in不为NULL,则它将指出具体的偏移位置。

fd_out/off_out参数的含义与fd_in/off_in相同,不过用于输出数据流。

len参数指定移动数据的长度

flags参数则控制数据如何移动,它可以被设置为下表中的某些值的按位或。

image-20220816100934412

阅读全文 »