1:sloop_init()

  初始化主要是初始化静态sloop_*** 结构体和填充struct sloop_data 结构体中的成员。

 //初始化静态存储区给sloop_***结构体
static struct sloop_socket _sloop_sockets[MAX_SLOOP_SOCKET];
static struct sloop_timeout _sloop_timeout[MAX_SLOOP_TIMEOUT];
static struct sloop_signal _sloop_signals[MAX_SLOOP_SIGNAL]; /* sloop module initialization */
void sloop_init(void * sloop_data)
{
memset(&sloop, , sizeof(sloop));
INIT_DLIST_HEAD(&sloop.readers);
INIT_DLIST_HEAD(&sloop.writers);
INIT_DLIST_HEAD(&sloop.signals);
INIT_DLIST_HEAD(&sloop.timeout);
INIT_DLIST_HEAD(&sloop.free_sockets);
INIT_DLIST_HEAD(&sloop.free_timeout);
INIT_DLIST_HEAD(&sloop.free_signals);
init_list_pools();
pipe(sloop.signal_pipe);
sloop.sloop_data = sloop_data;
} /* initialize list pools */
static void init_list_pools(void)
{
int i;
memset(_sloop_sockets, , sizeof(_sloop_sockets));
memset(_sloop_timeout, , sizeof(_sloop_timeout));
memset(_sloop_signals, , sizeof(_sloop_signals));
for (i=; i<MAX_SLOOP_SOCKET; i++) dlist_add(&_sloop_sockets[i].list, &sloop.free_sockets);
for (i=; i<MAX_SLOOP_TIMEOUT;i++) dlist_add(&_sloop_timeout[i].list, &sloop.free_timeout);
for (i=; i<MAX_SLOOP_SIGNAL; i++) dlist_add(&_sloop_signals[i].list, &sloop.free_signals);
}

  执行完sloop_init函数之后,静态数组_sloop_sockets、_sloop_signals、_sloop_timeout中的所有成员都被挂载到了sloop.free_sockets、sloop.free_timeout、sloop.free_signals这三个双链表中,表示可使用的链表,等待调用者。

2:sloop_run()

  此函数启动循环进行监听,监听是sloop.terminate全局变量控制,这个变量由信号控制。

 void sloop_run(void)
{
fd_set rfds;
fd_set wfds;
struct timeval tv, now;
struct sloop_timeout * entry_timeout = NULL;
struct sloop_socket * entry_socket;
struct sloop_signal * entry_signal;
struct dlist_head * entry;
int max_sock;
int res;
int sig;
// 开始循环
while (!sloop.terminate) {
/* 是否有定时器加入 */
if (!dlist_empty(&sloop.timeout)) {
entry = sloop.timeout.next;
entry_timeout = dlist_entry(entry, struct sloop_timeout, list);
} else {
entry_timeout = NULL;
}
/* 有定时器 */
if (entry_timeout) {
/* 获取当前时间 */
gettimeofday(&now, NULL);
/* 当前时间>=定时器表示应该执行定时器的回调函数了 */
if (timercmp(&now, &entry_timeout->time, >= ))
tv.tv_sec = tv.tv_usec = ;/* tv是select函数的timeout,直接置0表示不阻塞 */
else
timersub(&entry_timeout->time, &now, &tv);/* 否则阻塞 '当前时间-到期时间' */
} /* 清空读写描述符集合 */
FD_ZERO(&rfds);
FD_ZERO(&wfds);
max_sock = ; /* 添加信号可读转状态 */
FD_SET(sloop.signal_pipe[], &rfds);
if (max_sock < sloop.signal_pipe[]) max_sock = sloop.signal_pipe[]; /* 添加套接字可读转状态 */
for (entry = sloop.readers.next; entry != &sloop.readers; entry = entry->next) {
entry_socket = dlist_entry(entry, struct sloop_socket, list);
FD_SET(entry_socket->sock, &rfds);
if (max_sock < entry_socket->sock) max_sock = entry_socket->sock;
}
/* 添加套接字可写转状态 */
for (entry = sloop.writers.next; entry != &sloop.writers; entry = entry->next) {
entry_socket = dlist_entry(entry, struct sloop_socket, list);
FD_SET(entry_socket->sock, &wfds);
if (max_sock < entry_socket->sock) max_sock = entry_socket->sock;
} d_dbg("sloop: >>> enter select sloop !!\n");
res = select(max_sock + , &rfds, &wfds, NULL, entry_timeout ? &tv : NULL); if (res < ) {
/* 意外被中断 */
if (errno == EINTR) {
d_info("sloop: sloop_run(): EINTR!\n");
continue;
} else {
d_error("sloop: sloop_run(): select error (%s)!\n", strerror(errno));
break;
}
} /* 先检查信号 */
if (res > && FD_ISSET(sloop.signal_pipe[], &rfds)) {
if (read(sloop.signal_pipe[], &sig, sizeof(sig)) < ) {
/* probabaly just EINTR */
d_error("sloop: sloop_run(): Could not read signal: %s\n", strerror(errno));
} else if (sig == ) {
d_info("sloop: get myself signal !!\n");
} else if (!dlist_empty(&sloop.signals)) {
for (entry = sloop.signals.next; entry != &sloop.signals; entry = entry->next) {
entry_signal = dlist_entry(entry, struct sloop_signal, list);
/* 通过信号值找到登记的信号结构体并执行回调函数 */
if (entry_signal->sig == sig) {
if (entry_signal->handler(entry_signal->sig, entry_signal->param, sloop.sloop_data) < ) {
dlist_del(entry);
free_signal(entry_signal);
}
break;
}
}
if (sloop.terminate) break;
} else {
SLOOPDBG(d_info("sloop: should not be here !!\n"));
}
} /* 检查定时器 */
if (entry_timeout) {
if (sloop.timeout.next == &entry_timeout->list) {
gettimeofday(&now, NULL);
if (res == || timercmp(&now, &entry_timeout->time, >= )) {
/* 当前时间>=到期时间就调用回调函数 */
if (entry_timeout->handler)
entry_timeout->handler(entry_timeout->param, sloop.sloop_data);
dlist_del(&entry_timeout->list);//删除了定时器
free_timeout(entry_timeout);//将此定时器又归还给free_timeout双链表
}
} else {
SLOOPDBG(d_info("sloop: timeout (0x%x) is gone, should be canceled !!!\n", entry_timeout));
}
} /* 检查可读状态 */
if (!dlist_empty(&sloop.readers)) {
entry = sloop.readers.next;
while (entry != &sloop.readers) {
/* dlist_entry函数通过list指针获得指向list所在结构体的指针 */
entry_socket = dlist_entry(entry, struct sloop_socket, list);
if (FD_ISSET(entry_socket->sock, &rfds))/* 读状态就绪执行回调函数 */
res = entry_socket->handler(entry_socket->sock, entry_socket->param, sloop.sloop_data);
else
res = ;
entry = entry->next; /* 不同于定时器,只有回调函数返回错误才将此结构归还给free_readers,否则一直会监听此描述符 */
if (res < ) {
dlist_del(&entry_socket->list);
free_socket(entry_socket);
}
}
} /* 检查可写状态 */
if (!dlist_empty(&sloop.writers)) {
entry = sloop.writers.next;
while (entry != &sloop.writers) {
entry_socket = dlist_entry(entry, struct sloop_socket, list);
if (FD_ISSET(entry_socket->sock, &wfds))
res = entry_socket->handler(entry_socket->sock, entry_socket->param, sloop.sloop_data);
else
res = ;
entry = entry->next; if (res < ) {
dlist_del(&entry_socket->list);
free_socket(entry_socket);
}
}
}
}
/* 在退出循环时要将所有的都归还给free_***结构体 */
sloop_cancel_signal(NULL);
sloop_cancel_timeout(NULL);
sloop_cancel_read_sock(NULL);
sloop_cancel_write_sock(NULL);
}

  目前来讲,在sloop_data结构体中,struct dlist_head readers,struct dlist_head writers,struct dlist_head signals,struct dlist_head timeout,等链表都是空的,所以sloop_run其实没有做任何工作,要想真正起作用就需要将需要监听的套接字、定时器、信号等加入上上面三个链表中来。下一篇:sloop公共函数之添加信号,定时器及socket

sloop公共程序之初始过程及启动的更多相关文章

  1. sloop公共程序之总体描述

    1:功能需求 开发一个公共库文件sloop.c,实现三个常用功能以供其它模块调用.三个功能如下: 功能一:实现一般的信号监听,调用模块只需传入要监听的信号和相应的回调函数就可以在信号到时调用回调函数处 ...

  2. Android系统默认Home应用程序(Launcher)的启动过程源代码分析

    在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还需要有一个 Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home ...

  3. Android应用程序组件Content Provider的启动过程源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6963418 通过前面的学习,我们知道在Andr ...

  4. Android系统默认Home应用程序(Launcher)的启动过程源码分析

    在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还须要有一个Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home应 ...

  5. C程序编译执行过程

    C程序编译执行过程   认识C编译执行过程,是C学习的开端. 简单说C语言从编码编译到执行要经历一下过程:   C源代码 编译---->形成目标代码,目标代码是在目标机器上运行的代码. 连接-- ...

  6. Java内存解析 程序的执行过程

    Java内存解析 栈.堆.常量池等虽同属Java内存分配时操作的区域,但其适用范围和功用却大不相同.本文将深入Java核心,简单讲解Java内存分配方面的知识. 首先我们先来讲解一下内存中的各个区域. ...

  7. c语言编写51单片机中断程序,执行过程是怎样的?

    Q:c语言编写51单片机中断程序,执行过程是怎样的? 例如程序:#include<reg52.h>  void main(void)  {   EA=1;      //开放总中断   E ...

  8. Java Web项目,Android和微信小程序的初始页面配置

    Java Web项目 我们在Eclipse里开了Java Web项目之后,Run As Tomcat或者Apache服务器,本地运行,如果直接用http://localhost:8080访问项目,会发 ...

  9. hello程序的运行过程-从计算机系统角度

    hello程序的运行过程-从计算机系统角度 1.gcc编译器驱动程序读取源程序文件hello.c,并将它翻译成一个可执行目标文件hello.翻译过程分为四个阶段:预处理阶段,编译阶段,汇编阶段,链接阶 ...

随机推荐

  1. spring第一章

    spring第一章 一.概述 Spring是一个开源框架,它由Rod Johnson创建.它是为了解决企业应用开发的复杂性而创建的.Spring使用基本的JavaBean来完成以前只可能由EJB完成的 ...

  2. CSS3实现图片渐入效果

    很多网站都有那种图片渐入的效果,如:http://www.mi.com/minote/,这种效果用css3和一些js实现起来特别简单. 拿我之前做的页面来说一下怎么利用css3来实现图片渐入效果. 下 ...

  3. Java访问控制

    转自:菜鸟教程

  4. sql数据库表容量

    标题:SQL Server 的最大容量规范 数据库的文件大小,文件数量都有限制. 表的大小也有限制,如果表过大,查询效率就会下降,考虑对数据进行分割,对历史数据进行独立存储.

  5. Java中的网络编程-2

    Socket编程:(一般的网络编程) <1> 两个 JAVA 应用程序可通过一个双向的网络通信连接, 实现数据交换, 这个双向链路的一段称为一个 Socket. <2> Soc ...

  6. 《剑指offer》--- 两个链表的第一个公共结点

    本文算法使用python3实现 1. 问题   输入两个链表,找出它们的第一个公共结点.   时间限制:1s:空间限制:32768K 2 思路描述   使用两个指针 $ p1,p2 $ 分别指向两个链 ...

  7. TCP系列41—拥塞控制—4、Linux中的慢启动和拥塞避免(一)

    一.Linux中的慢启动和拥塞避免 Linux中采用了Google论文的建议把IW初始化成了10了.在linux中一般有三种场景会触发慢启动过程 1.连接初始建立发送数据的时候,此时cwnd初始化为1 ...

  8. 奇异值分解(SVD) --- 几何意义 (转载)

    PS:一直以来对SVD分解似懂非懂,此文为译文,原文以细致的分析+大量的可视化图形演示了SVD的几何意义.能在有限的篇幅把 这个问题讲解的如此清晰,实属不易.原文举了一个简单的图像处理问题,简单形象, ...

  9. 第166天:canvas绘制饼状图动画

    canvas绘制饼状图动画 1.HTML <!DOCTYPE html> <html lang="en"> <head> <meta ch ...

  10. 第163天:js面向对象-对象创建方式总结

    面向对象-对象创建方式总结 1. 创建对象的方式,json方式 推荐使用的场合: 作为函数的参数,临时只用一次的场景.比如设置函数原型对象. var obj = {}; //对象有自己的 属性 和 行 ...