随笔-99  评论-224  文章-30  trackbacks-0
 
     摘要:    接上篇初始化与创建,本篇阐述Socket操作和销毁两部分的实现。 Socket操作    系统调用read(v)、write(v)是用户空间读写socket的一种方法,为了弄清楚它们是怎么通过VFS将请求转发到特定协议的实现,下面以read为例(write同理),并假定文件描述符对应的是IPv4 TCP类型的socket...  阅读全文
posted @ 2015-05-03 16:55 春秋十二月 阅读(4697) | 评论 (0)编辑 收藏
     摘要: 引言    在Unix的世界里,万物皆文件,通过虚拟文件系统VFS,程序可以用标准的Unix系统调用对不同的文件系统,甚至不同介质上的文件系统进行读写操作。对于网络套接字socket也是如此,除了专属的Berkeley Sockets API,还支持一些标准的文件IO系统调用如read(v)、write(v)和close等。那么为什么socket也支持文件IO系统调...  阅读全文
posted @ 2015-05-03 16:31 春秋十二月 阅读(7438) | 评论 (0)编辑 收藏
     摘要: 字符集合     依据RFC3986 2规范,HTTP URI中允许出现的US-ASCII字符的子集,可以分成保留、未保留及转义这几类,每类的全部字符列表如下       ● 保留:  : / ? # [ ] @ ! $ & '( ) * + ,; =共18个,一般...  阅读全文
posted @ 2015-02-10 18:40 春秋十二月 阅读(4204) | 评论 (1)编辑 收藏
     摘要: 脚本概述   nginx是一款著名的开源web服务器,为方便升级与恢复,编写了一个简单的脚本,因为升级备份了可执行文件和配置文件(后缀名为old),所以可用于恢复。当升级时,若nginx正在运行,则不中断服务进行平滑升级,否则直接拷贝覆盖;当恢复时,若nginx正在运行,则不中断服务进行平滑恢复,否则直接拷贝覆盖。是否正在运行根据pid来判断,而pid从pid文件读取...  阅读全文
posted @ 2015-01-19 00:36 春秋十二月 阅读(1692) | 评论 (0)编辑 收藏
     摘要:    本文描述了一种简单的跨平台锁框架的设计与实现,该框架小巧实用、易于扩展,它的特点如下:      ● 实现了线程间互斥锁      ● 实现优化了单线程环境中的空锁和空级别锁      ● 支持编译时或运行时选择锁   ...  阅读全文
posted @ 2014-12-28 23:38 春秋十二月 阅读(1961) | 评论 (6)编辑 收藏
   众所周知,TLS是指线程局部存储,FIFO是Unix中的命名管道,可用于无关进程间的通信,而本文描述的TLS FIFO是指这样一种机制:如果一个线程在每次IO操作时,若没有连接,则先连接到FIFO服务端,再将连接关联到这个线程的TLS中,这里的连接即创建并打开唯一的FIFO,之后的读写就在这个FIFO连接上进行;当FIFO连接断开时,在下次IO操作时会自动重连。这样一来,用户程序就只要调用相关的IO操作,而不必管理连接,极大地简化了程序。使用FIFO通信前先要创建FIFO再打开它,其中创建是最重要的操作,结果有3种情况:成功、失败和已存在。

结构定义
typedef struct 
{
    int fd;
    char *name;
}ipc_fifo_t;
  fd存储FIFO文件描述符,name存储FIFO文件系统路径名。

接口函数
   创建FIFO
ipc_fifo_t* ipc_fifo_make(const char *path,mode_t mode);
  path指定FIFO路径,可以是绝对路径或相对路径,mode指定访问权限,若成功则返回一个FIFO结构,否则为NULL;通常被ipc_fifo_open调用。
   
   打开FIFO
int ipc_fifo_open(ipc_fifo_t **f,const char *path,int flag,mode_t mode);
  flag指定打开标志,如果包含了O_CREAT标志,那么调用ipc_fifo_make创建新的FIFO对象并在打开成功后替换*f,否则如果*f为空,就分配并初始化一个fifo结构;mode指定访问权限,仅当创建时生效。虽然f为输入输出参数,但操作失败时不会影响它,也就是说没有副作用。

  ● 发送数据   
ssize_t ipc_fifo_write(ipc_fifo_t *f,const void *data,size_t size);
  如果成功则返回已发送的字节数,否则返回-1,errno表示出错代码。
   
  ● 接收数据
ssize_t ipc_fifo_read(ipc_fifo_t *f,void *data,size_t size);
  如果成功则返回已发送的字节数,否则返回-1,errno表示出错代码。

  ● 关闭FIFO
void ipc_fifo_close(ipc_fifo_t *f);
  当通信结束的时候,应该调用此函数来关闭FIFO,它会先删除FIFO文件和关闭文件描述符,最后释放fifo结构。

  ● 获取TLS FIFO
ipc_fifo_t* ipc_fifo_tls_get();
  该函数一般被发送数据接口调用,若成功则返回一个FIFO结构,否则为NULL;每个线程对应一个FIFO对象,对于同一线程,获取的是同一个FIFO对象,而后便可调用ipc_fifo_write来发送数据。

工作流程
  创建FIFO
  适用于FIFO客户端和服务端,但服务端由于要异步处理众多FIFO客户端,因此要注意以下2个问题,这也是使用FIFO技术通信的一些细节。
  1)必须以非阻塞读写方式打开知名FIFO,即以O_CREAT|O_RDWR|O_NONBLOCK标志来调用ipc_fifo_open,这样才不会阻塞等待某个客户端以同步写方式打开知名FIFO而返回,因为它使用O_RDWR标志,这样自己既读又写,加上O_NONBLOCK,就立即返回了。
  2)必须以非阻塞只读方式打开对应客户端FIFO,即以O_RDONLY|O_NONBLOCK标志调用ipc_fifo_open,这样就不会阻塞接受客户端建立连接而返回。

  建立FIFO连接
  适用于FIFO客户端,被发送数据接口调用,考虑到服务端可能事先没有打开知名FIFO来监听连接,所以这里先以异步方式写打开知名FIFO如果成功则改以阻塞方式发送唯一路径名到服务端,如果发送完全后,接着以同步方式写打开唯一FIFO,这是为了等待服务端打开了对应的唯一FIFO。

  发送数据

  适用于FIFO客户端,当TLS中没有关联对应的FIFO时,则先调用fifo_tls_get进入建立FIFO连接流程,而后再发数据。
posted @ 2014-12-01 00:13 春秋十二月 阅读(1041) | 评论 (2)编辑 收藏
     摘要:    Web服务器为了支持https访问,通常会使用第三方库openssl实现,而且为了高性能采用异步事件驱动模型,因此连接套接字被设为非阻塞类型,本文在nginx ssl模块的基础上,简化提取它的核心框架,使用面向对象的方式描述,从握手、读写和关闭3个方面进行了分析,由于这3个操作都是异步的,因此操作失败后要调用SSL_get_error来获取错误码,有如下4种情况。 &n...  阅读全文
posted @ 2014-04-11 17:26 春秋十二月 阅读(10867) | 评论 (0)编辑 收藏
模板
    1. 空基类优化
    2. 元编程技术
        2.1. 选择API
        2.2. 计算最值
        2.3. 类型选择
    3. 封装GCC原子操作
    4. 定制类对象的内存管理

算法
    1. 排序
        1.1. 改进的快速排序
        1.2. 原位统计排序     
    2. 多叉树
        2.1. 深度优先存储
        2.2. 迭代器的设计
        2.3. 前序遍历
        2.4. 后序遍历
        2.5. 兄弟遍历
        2.6. 叶子遍历
        2.7. 深度遍历 
    3. 优先级队列
        3.1. 原理
        3.2. 内幕
        3.3. 外观
    4. RSA加解密的证明
    5. DSA数字签名的推导

GUI
 
    1. MFC中的WM_COMMAND传递
    2. ATL和WTL中的消息反射
    3. 工作线程与消息循环
    4. 多窗口的组合与分离
        4.1. 接口
        4.2. 实现

跨平台
    1. 用户态自旋锁
    2. 互斥锁
    3. 信号量
    4. socket管道
    5. 锁框架的设计与实现

网络
    1. 运用状态机异步接收变长包
    2. 基于OpenSSL实现的安全连接
    3. TCP/IP FAQ
        3.1. 链路层、网络层和传输层
        3.2. 插口层和应用层
    4. Linux套接字与虚拟文件系统
        4.1. 初始化和创建
        4.2. 操作和销毁
    5. Linux ICMP消息的产生与转换
    6. nginx iocp
        6.1. tcp异步连接
        6.2. udp异步接收
        6.3. scm服务控制
    7. TCP分组丢失时的状态变迁
    8. 基于ENet实现可靠UDP通信的同步模型

Shell应用
    1. 自动生成并安装服务脚本
    2. nginx升级与恢复
    3. 使用awk定位反汇编输出
    4. 自动化批量编译
posted @ 2014-04-10 16:04 春秋十二月 阅读(1629) | 评论 (0)编辑 收藏
   为了方便更改系统tcp内核的一些参数,编写ktcpopt脚本如下
1#! /bin/bash 
2# ktcpopt 
3
4sed -i '/net.ipv4.tcp_syncookies\|net.ipv4.tcp_tw_reuse\|net.ipv4.tcp_tw_recycle\|net.ipv4.tcp_fin_timeout\|net.ipv4.tcp_max_syn_backlog\|net.ipv4.tcp_max_tw_buckets\|net.ipv4.ip_local_port_range/d' /etc/sysctl.conf
5
6sed -i '$a\net.ipv4.tcp_syncookies=1\nnet.ipv4.tcp_tw_reuse=1\nnet.ipv4.tcp_tw_recycle=1\nnet.ipv4.tcp_fin_timeout=30\nnet.ipv4.tcp_max_syn_backlog=8192\nnet.ipv4.tcp_max_tw_buckets=5000\nnet.ipv4.ip_local_port_range=10000 65000' /etc/sysctl.conf

  为了方便配置程序的崩溃调试,编写coredump脚本如下
1#! /bin/bash
2# coredump
3
4sed -i '/ulimit -c unlimited\|export core_path=\/tmp\/corefiles\|mkdir -p $core_path\|echo "0" > \/proc\/sys\/kernel\/core_uses_pid\|echo "$core_path\/%e" > \/proc\/sys\/kernel\/core_pattern/d' ~/.bashrc
5
6sed -i '$a\ulimit -c unlimited\nexport core_path=/tmp/corefiles\nmkdir -p $core_path\necho "0" > /proc/sys/kernel/core_uses_pid\necho "$core_path/%e" > /proc/sys/kernel/core_pattern' ~/.bashrc

   从以上2个脚本可以看出,为避免每次调用脚本时增加重复行以致配置文件逐渐变大,先删除已经存在的相关配置,再在末尾增加。这里使用了sed来实现直接在文件中删除和增加,其中由于删除操作的匹配模式有多个,因此使用了|符号并用\转义,并且第2个脚本模式文本中含有/符号,这与sed本身的模式限定符/存在歧义,因此也用了\转义;增加使用$a\命令来实现在文件末尾增加配置,并用\n换行。
posted @ 2014-03-24 18:44 春秋十二月 阅读(1138) | 评论 (0)编辑 收藏
脚本概述
   一般地,当在目标机器编译安装某个服务程序后,为了使服务能开机自启动和关机自停止,则需要将其添加为系统服务。但不同的Linux系统管理服务的方法不同,如Ubuntu使用update-rc.d命令,而RedHat则使用chkconfig命令。因此为了能自动识别系统的类型,减少人工控制,编写了一个简单的autosrv脚本,要求至少1个最多2个参数,特点如下:
   ● 第1个参数只能为install或uninstall,表示安装或卸载服务。
   ● 第2参数是可选的,表示系统名称,如果没有指定,那么会自动识别,若出现提示错误,则表示应该要显式指定系统名称了。

脚本实现
  1#! /bin/bash
  2# autosrv
  3
  4if [ $# -lt 1 ]; then
  5    echo "Usage: $(basename "$0") install | uninstall [sysname]"
  6    exit
  7elif [ "$1" != "install" -a "$1" != "uninstall" ]; then
  8    echo "The first parameter must be install or uninstall" 
  9    exit
 10fi
 11
 12action=$1
 13sysname=$2
 14srv_path=/etc/init.d/srv_name
 15
 16if [ -z "$sysname" ]; then
 17    sysname=`lsb_release -a | sed -n '2p' | awk '{if($0~/[Uu][Bb][Uu][Nn][Tt][Uu]/) print "ubuntu"; else if($0~/[Dd][Ee][Bb][Ii][Aa][Nn]/) print "debian"; else if($0~/[Rr][Ee][Dd][Hh][Aa][Tt]/) print "redhat"; else if($0~/[Cc][Ee][Nn][Tt][Oo][Ss]/) print "centos"; else print ""}'`
 18    if [ -z "$sysname" ]; then
 19        echo "Unknown system, please manual special it with the second parameter"
 20        exit
 21    fi
 22    echo "Current system is $sysname"
 23fi
 24
 25create_file_ubuntu_debian()
 26{
 27cat << END > $srv_path
 28#! /bin/bash
 29. /lib/lsb/init-functions
 30
 31END
 32cat srv_name.body >> $srv_path
 33}
 34
 35create_file_redhat_centos()
 36{
 37cat << END > $srv_path
 38#! /bin/bash
 39#chkconfig:2345 90 10
 40#description: srv name
 41
 42. /etc/rc.d/init.d/functions
 43
 44END
 45cat srv_name.body >> $srv_path
 46}
 47
 48chmod_file()
 49{
 50    chmod u+x $srv_path
 51}
 52
 53remove_file()
 54{
 55    rm -f $srv_path
 56}
 57
 58install_ubuntu_debian()
 59{
 60    create_file_ubuntu_debian
 61    chmod_file
 62    update-rc.d srv_name defaults 90 10
 63}
 64
 65uninstall_ubuntu_debian()
 66{
 67    update-rc.d -f srv_name remove
 68    remove_file
 69}
 70
 71install_redhat_centos()
 72{
 73    create_file_redhat_centos
 74    chmod_file
 75    chkconfig --add srv_name
 76}
 77
 78uninstall_redhat_centos()
 79{
 80    chkconfig --del srv_name
 81    remove_file
 82}
 83
 84case "$sysname" in
 85    ubuntu|debian)
 86    if [ "$action" = "install" ]; then
 87        install_ubuntu_debian
 88    else
 89        uninstall_ubuntu_debian
 90    fi
 91    ;;
 92
 93    redhat|centos)
 94    if [ "$action" = "install" ]; then
 95        install_redhat_centos
 96    else
 97        uninstall_redhat_centos
 98    fi
 99    ;;
100
101    *)
102    echo "Currently only support ubuntu, debian, redhat and centos system"
103    exit
104    ;;
105esac
   从上可知,自动识别的方法是获取lsb_release -a返回的文本再使用awk来匹配ubuntu,redhat,debian,centos这几个子串(忽略大小写)。要注意的是,返回的文本可能有所不同。

   当系统安装了LSB模块时,返回结果如下
   

   没有安装时,返回结果如下
   
   无论哪种情况,要提取分析的都是第2行文本,因此使用了sed -n '2p'。srv_name.body是不同系统相同的用于生成最终服务脚本的部分代码文件,通常包含了start,stop,status,restart几个函数,只是没有包含前面的一部分,而这部分则由autosrv脚本来根据不同的系统生成不同的代码。
posted @ 2014-01-03 17:11 春秋十二月 阅读(1477) | 评论 (1)编辑 收藏
仅列出标题
共10页: 1 2 3 4 5 6 7 8 9 Last