邢栋博客

邢栋博客,Action博客,记录工作和生活中的点点滴滴

SELECT和EPOLL模式
SELECT和EPOLL模式

select模式
1.应用层首先初始化FD_SET(填入需要检测的socket集合),然后调用select函数
2.内核对FD_SET包含的所有socket进行了逐个检测,如果某个socket有状态发生,则填入内容分配一个数组,当所有socket都检查完成后,再将该数组copy到FD_SET中,然后返回应用层

3.select调用返回,应用层从返回的FD_SET中提取有状态发生的socket,并根据socket值映射客户端上下文(可以通过map或hash_map实现映射),然后处理收到的数据

epoll模式
1.应用层调用 epoll_wait检测有事件发生的连接
2.内核对epoll注册事件的socket进行跟踪,一旦某个socket有事件发生,便将其保存到一个内部数组。当接到应用层调用epoll_wait时,直接将该集合copy到epoll_wait数组返回给应用层即可,不需要象select模式对每个worker进行逐一检查。

3.epoll_wait调用返回,所有有事件发生的连接被填入一个epoll_event数组,应用层可根据epoll_event中的用户自定义变量 直接映射客户端上下文(不需要借助hash表),然后处理收到的数据

php代码执行过程简述
php代码的执行过程

扫描->解析->编译->执行->输出

1.扫描(scanning) 将index.php内容变成一个个语言片段(token)
<?php

$code =<<<'PHP_CODE'
<?php
//这是注释
echo "hello world\n";
$data = 1+1;
eval("echo 'Inception lvl 1...\n';");
echo $data;
PHP_CODE;
echo "<pre>";
print_r(token_get_all($code));

echo token_name(319);//输出 T_ECHO  ,260 T_EVAL(eval不是函数)

/*
 *   [16] => Array
        (
            [0] => 319  //tokenid,也就是词的id
            [1] => echo  //词具体的内容
            [2] => 5 //所在的位置,行数
        )
 *
 */

?>

2.解析(parsing) 将一个个语言片段变成有意义的表达式
3.编译(complication) 将表达式编译成中间码(opcode)  //可以使用vld扩展或者parsekit扩展查看
4.执行(execution) 将中间码一条条的执行
如果执行的是某内置函数,会调用对应的函数;
如果调用的是扩展,则会将控制权交给这些扩展,扩展执行完成后将结果返回给 zend engine
全部执行完成后zend engine将结果返回给php内核,内核再返回给sapi,最后返回给服务器,通过服务器httpresponse返回到浏览器

5.输出(output buffer) 将要输出的内容输出到缓冲区

linux中awk命令的简单介绍和使用

1.字段以:分隔,打印第一列
awk -F":" '{print $1}' /etc/passwd

2.字段以:分隔,打印第一列和第三列
awk -F":" '{print $1 $3}' /etc/passwd  
awk -F":" '{print $1":"$3}' /etc/passwd

3.文件形式的执行
vim test.awk 写入
BEGIN {FS=":"}
{print $1}

awk -f test.awk /etc/passwd

4.普通过滤代码块
字段以:分隔,输出 以a开头的第一列数数据
awk  'BEGIN{FS=":"}  /^a/{print $1}'  /etc/passwd  

字段以:分隔,输出第一列为root的一行数据
awk  'BEGIN{FS=":"}  $1=="root"{print $0}'  /etc/passwd 

字段以:分隔,输出第七列为nologin的第一列数数据
awk  'BEGIN{FS=":"}  $7 ~ "nologin"{print $1}'  /etc/passwd

字段以:分隔,输出不包含nologin 的第一列数数据
awk  'BEGIN{FS=":"}  !/nologin/{print $1}'  /etc/passwd


5.字段分隔符(FS)
FS="\t+"   一个或者多个TAB分隔
FS="[[:space:]+]"  一个或者多个空白分隔 ,默认的
FS="(foo|:)"  以foo或者:分隔
 
 
6.字段数量(NF)
NF: number of fileds 字段数量,通常只读
NF==3{print "字段为3的行:" $0}
第二列之后的数据

  if(NF>2){
    print $1 $2 $3
  }
}
 
7.记录数量(NR)
NR: number of records 记录(行)数量,当前awk遍历过的函数,动态变化
NR==3{print "第三行"}
#跳过前10行

  if(NR>10){
    print $0
  }
}
 
8.FS和RS例子
my.txt
路人甲
电话:110
手机:138110

路人乙
电话:120
手机:138120
 
awk 'BEGIN{FS="\n";RS=""} {print $1"\t"$2"\t"$3}' my.txt 
说明: FS="/n" 每一列以\n(换行)来分隔, RS=""每一行以空格来分隔

结果如下
路人甲 电话:110 手机:138110

路人乙 电话:120 手机:138120


9.OFS和ORS
OFS:字段输出分隔符,默认是" "
ORS:记录输出分隔符,默认为"\n"

my.txt
路人甲
电话:110
手机:138110

路人乙
电话:120
手机:138120
 
awk 'BEGIN{FS="\n";RS="";OFS="\t";ORS="\n"} {print $1,$2,$3}' my.txt
说明: 
  FS="/n" 每一列以\n(换行)来分隔, RS=""每一行以 【空行】 来分隔
  OFS="/t" 每一列输出用 \t 来分隔, ORS=""每一行以 \n换行 来分隔

结果如下
路人甲 电话:110 手机:138110
路人乙 电话:120 手机:138120

10.循环语句
my.txt
路人甲
电话:110
手机:138110

路人乙
电话:120
手机:138120
QQ:123456
 
awk 'BEGIN{FS="\n";RS="";ORS=""} {for(x=1;x<=NF;x++){print $x"\t"}print "\n"}' my.txt

结果如下
路人甲 电话:110 手机:138110
路人乙 电话:120 手机:138120    QQ:123456

linux中sed命令的几个简单事例


删除文件中1-10行的数据
sed -e '1,10d' ./myfile.txt 

删除文件中以#开头的行,即删除注释
sed -e '/^#/d' ./myfile.txt 

将每行第一次出现的xingdong替换成action
sed -e 's/xingdong/action/' ./myfile.txt

将每行所有的xingdong替换成action
sed -e 's/xingdong/actio/g' ./myfile.txt


把结果存储到文件
sed -e 's/xingdong/actio/g' ./myfile.txt > ./newfile.txt 
或者

sed -i 's/xingdong/actio/g' ./myfile.txt 


使用sed--格式

命令行格式
sed [options] 'command' file(s)
options  -e;-n
command 行定位(正则) + sed命令(操作)

命令行格式举例
1. sed -n '/root/p'
2. sed -e '10,20d' -e 's/false/true/g'

基本操作命令
1. -p 打印相关的行 需要和 -n 配合  sed -n 'p' /etc/passwd
2. -a(新增行) /i(插入行)   新增是在某行之后,插入是在之前
   -c(替代行)
   -d(删除行)
   
nl /etc/passwd | sed '1,5i===' //在1-5行之前插入=== 
nl /etc/passwd | sed '5i==='  //在5行之前插入===
sed '/^$/d' dt.php  //去除空行

3. -s(行首个字符替换) : 分隔符/,# 等
   -g(全局替换) 
sed -e 's/xingdong/actio/g' ./myfile.txt
sed -e 's/xingdong/action/' ./myfile.txt
   
   
高级操作命令
(1)
-{}:多个sed命令,用;分开  
nl passwd|sed '{20,30d;s/false/true/}'

(2)
-n 读取下一个输入行(用下一个命令处理)
nl /etc/passwd |sed -n '{n;p}'  //打印偶数行 同 nl /etc/passwd |sed -n '2~2p'
nl /etc/passwd |sed -n '{p;n}' //打印奇数行 同 nl /etc/passwd |sed -n '1~2p'

(3)
- &:替换固定字符串
cat  /etc/passwd|sed 's/^[a-z]\+/&  /'

案例1:大小写的转换
元字符 \u\l\U\L :转换为大写/小写字符
cat  /etc/passwd|sed 's/^[a-z]\+/\U&/'  //把用户名转换成大写
cat  /etc/passwd|sed 's/^[a-z]\+/\u&/'  //把用户名首字母转换成大写
ls *.php| sed 's/^\w\+/\U&/'  //把所有php文件名转换成大写
cat /etc/passwd| sed 's/\([a-z]\+\):x:\([0-9]\+\):\([0-9]\+\).*$/\1:\2:\3/'   //取 用户名:uid:gid

(4)
-\( \):替换某种(部分)字符串(\1,\2)

ifconfig eth0 | sed -n '/inet/p'| sed 's/inet \([0-9.]\+\).*$/\1/' // 取ip

(5)
-r:复制指定文件插入到匹配行
-w:复制匹配行拷贝到指定文件里

sed '1r 123.txt' abc.txt   //复制123.txt的文件内容到 abc.txt第一行后面,文件内容没改变
sed '1w abc.txt' 123.txt   //复制123.txt内容的第一行到abc.txt中(清空然后写入)
sed 'w abc.txt' 123.txt    //复制123.txt内容到abc.txt中(清空然后写入) 

(6)
q:退出sed

nl /etc/passwd | sed '/daemon/q'  //找到daemon所在的行然后退出
nl /etc/passwd | sed '10q'  //读取到第10行退出


sed -f scriptfile file(s)


关于shell函数的简单总结说明
shell函数说明

1.函数调用时,脚本的位置函数($* $@ $# $1...)会被替换为函数的参数,函数执行完毕后,会恢复原值

2.函数中的变量默认为全局作用域,除非使用local关键字定义

3.通过return 命令可以让函数返回数字值,常用于表示函数执行是否成功。如果返回字符串值,则需要在函数中使用echo,然后再在函数外使用$()捕获;或者将字符串存在一个变量中,函数执行完毕后读取该变量

4.如果函数中没有使用 return 指定返回值,则函数返回值为最后一条命令的退出码($?捕获返回值) 

5.简单事例

#!/bin/bash

foo()
{
  echo "is your name  $* ?"
  while true
  do
    echo -n "enter yes or no:"
    read x
    case $x in
        y|yes) return 0;;
        n|no) return 1;;
        *) echo "answer yes or no"
    esac
  done
}

echo "your parameters is $*"
if foo "$1"
then
  echo "hi $1,nice name"
else
  echo "never mind"
fi

exit 0



php之XMLReader简单事例

新建xml.xml

<?xml version="1.0" encoding="utf-8"?>  
<shows>  
    <show>  
        <name>action</name>
        <age>18</age>
        <sex>男</sex>
    </show>  
    <show>  
        <name>yiyi</name>
        <age>20</age>
        <sex>女</sex>
    </show>  
</shows>  
xml.php如下
<?php
    $items = [];
    $reader = new XMLReader();
    $reader->open('xml.xml','utf-8');

    while($reader->read()){
        if($reader->name == 'show' && $reader->nodeType == XMLReader::ELEMENT){
            $item = [];
            while($reader->read() && $reader->name != 'show'){
                if($reader->nodeType != XMLReader::ELEMENT)continue;

                $name = $reader->name;
                $value = $reader->readString();
                $item[$name]  = $value;
            }
            $items[] = $item;

        }

    }
    echo "<pre>";
    print_r($items);


文本文件和二进制文件相关以及php操作二进制文件
文本文件和二进制文件有什么不同

1.文本文件是基于字符编码的文件
2.除了文本文件以外的文件成为二进制文件
3.二进制文件编码是变长的,灵活利用率高
4.两者读写差别仅体现在回车换行符的处理上
5.文本文件是一种特殊的二进制文件


php写入和读取二进制文件 简单事例

//写入方式1
// $fh = fopen('my.db','w'); 
// $name  = pack('A20','zsf');//长度不足20会以空格补充
// $age = pack('S',1);
// $email = pack('a20','xingdong365@qq.com');//长度不足20会以null补充

// fwrite($fh,$name.$age.$email);

//写入方式2,同上
$fh = fopen('my_1.db','w');
$data = pack('A20Sa20','zsf',1,'xingdong365@qq.com');
fwrite($fh,$data);


$tmp = file_get_contents('my_1.db');
$data = unpack('A20name/Sage/a20email',$tmp);


print_r($data);


文件指针的定位操作

fseek() 在文件指针中定位
ftell() 返回文件指针读/写的位置
rewind() 返回文件指针的位置
feof() 测试文件指针是否达到了文件结束的位置

php的几个人坑人小题
<?php
	//----example 1
	$a = 3;
	$b =5;
	if($a = 5 || $b = 7){
		++$a;
		$b++;
	}
	echo $a,'--'.$b,"<br>"; //输出结果 为 1--6
	//说明
	// $a = 5 || $b =7 ,执行逻辑为 $a = (5||$b=7),$a = true,布尔型值++ 一直为1	

	//----example 2
	$count = 5;
	function get_count(){
		static $count = 0;
		return $count++;
	}
	++$count;  //此时$count为6
	get_count(); //函数里 返回的是 0, static $count 变成 1
	echo get_count(),"<br>";//输出结果为1 

	//----example 3
	echo count('567')+count(null)+count(false),"<br>"; //返回2 ,count(null)为0,其余的为1

	//----example 4
	$a = 0.2+0.7;
	$b = 0.9;
	var_dump($a == $b);//返回 false



优惠券
广告位-淘宝
最新微语