extern void addfd( int epollfd, int fd, bool one_shot );
extern void removefd( int epollfd, int fd );
在C和C++编程语言中,
extern
关键字用于声明一个变量或函数,表示其定义在另一个文件中。使用extern
可以在多个文件之间共享变量或函数。extern
的主要用途是声明一个在其他地方定义的全局变量或函数的引用,这对于跨文件访问和修改变量、调用函数特别有用。这种方式在大型项目中,特别是在需要将实现分散到多个文件中时,非常常见。使用
extern
声明变量当你在一个文件中声明一个带有
extern
的变量时,你告诉编译器这个变量的定义存在于程序的其他地方。这意味着存储空间不是在声明时分配的,而是在变量实际定义的地方分配。例子:
// File: main.c extern int counter; // 告诉编译器变量counter在别处定义 int main() { counter = 1; // 使用变量 return 0; } // File: counter.c int counter; // 定义并分配存储空间
在这个例子中,
counter
变量在counter.c
文件中定义,而在main.c
文件中通过extern
声明来引用。这允许main.c
访问并修改counter.c
中定义的counter
变量。使用
extern
声明函数对于函数,使用
extern
是可选的,因为在C和C++中,函数默认就是外部链接的。即便如此,你仍然可以在声明外部函数时使用extern
关键字,尽管这并不常见。例子:
// File: utils.c void printMessage() { // 实现 } // File: main.c extern void printMessage(); // 可选的,因为函数默认是extern的 int main() { printMessage(); // 调用函数 return 0; }
在这个例子中,即使没有在
main.c
中显式地使用extern
关键字,printMessage
函数也是可以被外部访问的,因为函数在C/C++中默认具有外部链接。但是,明确地使用extern
可以增强代码的可读性和意图表达。
void addsig(int sig, void( handler )(int)){
struct sigaction sa;
memset( &sa, '\0', sizeof( sa ) );
sa.sa_handler = handler;
sigfillset( &sa.sa_mask );
assert( sigaction( sig, &sa, NULL ) != -1 );
}
这段代码是用于设置信号处理函数的。在UNIX或Linux系统编程中,信号处理是一种处理异步事件的机制。下面是对这段代码的详细解释:
void addsig(int sig, void( handler )(int)){
这一行定义了一个名为
addsig
的函数,它接受两个参数:一个是int sig
,代表要处理的信号编号;另一个是函数指针void (*handler)(int)
,指向一个信号处理函数,这个函数接收一个int
类型的参数(通常是信号的编号),返回类型为void
。struct sigaction sa;
定义了一个
sigaction
结构体变量sa
。sigaction
结构体用于指定信号的处理方式,包括信号处理函数、信号掩码和其他选项。memset( &sa, '\0', sizeof( sa ) );
使用
memset
函数初始化sa
结构体,将其设置为0。这确保了结构体的所有成员都被清零,避免了未初始化的成员可能导致的不确定行为。sa.sa_handler = handler;
将
sa_handler
成员设置为参数中提供的handler
函数。sa_handler
是一个函数指针,指向信号处理函数。当接收到sig
指定的信号时,将执行handler
函数。sigfillset( &sa.sa_mask );
sigfillset
函数将sa.sa_mask
信号集初始化,包括系统中所有的信号。这意味着在信号处理函数执行时,几乎所有的信号都将被阻塞,不会中断信号处理函数的执行。这是为了避免信号处理过程中发生的竞争条件。assert( sigaction( sig, &sa, NULL ) != -1 );
调用
sigaction
函数将sig
信号的处理方式设置为sa
指定的方式。如果sigaction
调用成功,它会返回0;如果失败,返回-1。assert
语句确保了sigaction
调用成功。如果sigaction
调用失败(即返回-1),assert
将终止程序。总结来说,这段代码的作用是为特定的信号
sig
注册一个新的处理函数handler
,在信号处理期间阻塞其他信号,以确保信号处理的原子性和顺序性。