- 浏览: 146463 次
-
最新评论
文章列表
在系统底层,除了整数寄存器,CPU 还维护着一组单个位的条件码(condition code)寄存器,它们描述了最近的算术或逻辑操作的属性。可以检测这些寄存器来执行条件分支指令。最常用的条件码有:
(1)CF:进位标志。最近的操作使最高位产生了进位。可用来检查无符号操作的溢出。
(2)ZF:零标志。最近的操作得出的结果为 0。
(3)SF:符号标志。最近的操作得到的结果为负数。
(4)OF:溢出标志。最近的操作导致一个补码溢出——正溢出或负溢出。
在汇编指令之算术和逻辑操作指令一节的指令中,除 lea ...
Reids 数据库通知功能可以让客户端通过订阅给定的频道或者模式,来获知数据库中键的变化,以及数据库中命令的执行情况。
比如,以下代码展示了客户端如何获取 0 号数据库中针对 message 键执行的所有命令。
redis> SUBSCRIBE __keyspace@0__:message
Reading messages... (press Ctrl-C to quit)
1) "subscribe" // 订阅信息
2) "__keyspace@0__:message" ...
下表是 x86-64 中的一些整数和逻辑操作指令,其中除 leaq 指令外,其他指令类都有各种不同大小操作数的变种(类似于 MOV 类指令,见汇编指令之数据传送指令)。例如,指令类 ADD 由四条加法指令组成:addb、addw、addl ...
在Unix 域套接字概述一节中介绍了什么是 Unix 及相关函数,本文将继续介绍 Unix 域套接字在进程间传递描述符的应用。
在进程间传递打开的描述符时通常会采用如下两种方法:
(1)fork 调用返回后,子进程自动共享父进程的所有打开的描述符。
(2)exec 调用执行后,所有描述符通常保持打开状态不变。
第一种方法中,进程先打开一个描述符,再调用 fork,之后父进程关闭这个描述符,子进程则处理该描述符。这样一个打开的描述符就从父进程传递到子进程。不过有时候可能想让子进程打开一个描述符并把他传递给父进程。
...
在x86-64 中的寄存器与汇编操作数杂述一节中,我们介绍了 x86-64 中的 16 种寄存器和各种操作数寻址方式,本文将在此基础上介绍汇编中的数据传送指令。
最简单形式的数据传送指令如下表所示。这些指令 ...
Redis 服务器将其所有的数据库都保存在 redisServer 结构的 db 数组中,db 数组中的每项都是一个 redisDb 结构,代表一个数据库。而在服务器内部,客户端当前的目标数据库则都保存在 redisClient 结构的 db 属性中。这三个结构的关键定义如下。
struct redisServer{
/* ... */
redisDb *db; // 用于保存服务器中的所有数据库的数组
int dbnum; // 服务器的数据库数量
/* ... */
};
typedef st ...
Intel 中常用术语“字(word)”表示 16 位数据类型,因此 32 位数称为“双字(double words)”,64 位数称为“四字(quad words)”。下表中给出了 C 语言基本数据类型对应的 x86-64 表示。
如图所示,大多数 GCC ...
Unix 域协议并不是一个实际的协议族,而是在单个主机上执行客户/服务器通信的一种方法,所用的 API 就是在不同主机上执行客户/服务器通信所用的套接字 API,可视为进程间通信(IPC)方法之一(POSIX 也把 Unix 域协议称为“本地 IPC”)。
Unix 域提供了两类套接字:字节流套接字(类似 TCP)和数据报套接字(类似 UDP)。尽管也提供原始套接字,不过不曾见过使用。使用 Unix 域套接字有以下 3 个理由。
(1)Unix 域套接字往往比位于同一个主机的 TCP 套接字快一倍。X Window System 就发挥了这个优势。 ...
kqueue 接口是从 FreeBSD 4.1 版引入的,它允许进程向内核注册描述所关注 kqueue 事件的事件过滤器。类似于 select,它也可以设置超时,此外,它还有异步 I/O、文件修改通知(例如文件被删除或修改时发出的通知)、进程 ...
辅助数据(ancillary data)也称控制信息(control information)。在recv/send 和 recvmsg/sendmsg 函数一节中介绍 sendmsg 和 recvmsg 函数时提到,可以使用 msghdr 结构中的 msg_control 和 msg_controllen 成员来发送和接收辅助数据。
...
recv 和 send 函数类似于标准的 read 和 wirte 函数,不过多了一个额外的参数。
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags);
ssize_t send(int sockfd, const void *buff, size_t nbytes, int flags);
...
阅读本节前需要阅读 Redis 对象系统概览一节。此外,对于各个对象底层中所用到的数据结构,请阅读前面的相关博文笔记,此次不再赘述。
在 Redis 的五种类型的对象中,字符串对象是唯一一种会被其他四种类型对象嵌套的对象。字符串对象的编码可以是 int、raw 或者 embstr。
如果一个字符串对象保存的是整数值,并且该值可以使用 long 型表示,则该对象结构的 ptr 属性里面保存的就是整数值(会将 void* 转换成 long),并同时将其 encoding 属性设置为 int。但如果该整数值超过了 long 型所能表示的数值范围,则使用下 ...
在 4.3 BSD 系统之前,很多网络服务都是单独关联了一个进程,每个进程都占据了一个进程表项,而且这些进程几乎都含有相同的启动代码,并且大部分时间都处于睡眠状态。为了简化这些问题,4.3 BSD 中提供了一个因特网超级服务器(即 inetd 守护进程),使得基于 TCP 或 UDP 的服务器都可以使用这个守护进程。下面就来看一下该进程是如何解决上述问题的。
inetd 进程在演变成守护进程后,会接着读入并处理自己的配置文件。通常是 /etc/inetd.conf 配置文件指定 inetd 处理哪些服务以及如何处理服务请求。该文件每行中一般包含如下图所示的字段(现 ...
前面介绍了 Redis 中用到的所有主要数据结构,如简单动态字符串、双端链表、字典、压缩列表和整数集合等,不过 Redis 并没有直接使用这些数据结构来实现键值对数据库,而是基于这些数据结构创建了一个对象系统,该系统包含字符串对象、列表对象、哈希对象、集合对象和有序集合对象这五种类型的对象,每种对象都至少使用了一种数据结构。
通过这五种不同类型的对象,Redis 可以在执行命令之前,根据对象的类型来判断一个对象是否可以执行给定的命令。此外,还可以针对不同的使用场景来为对象设置多种不同的数据结构实现,从而优化对象在不同场景下的使用效率。
Redis ...
源文件 hello.c 的代码如下:
#include <stdio.h>
int main(){
printf("hello world!");
return 0;
}
要运行该程序,需要编译器驱动程序将其翻译成可执行的目标文件 hello,这个过程可分为如下图所示 ...