Akawa

ETY001的博客

This function not exists for mysqli db extension. For Persistent Connections can use p: prefix by hostname at php 5.3.

fix:

function mysqli_pconnect($host, $username, $password, $new_link = false, $port = 0)
{
    if($port)
    {
        mysqli_connect("p:".$host, $username, $password, $new_link, $port);
    }
    else
    {
        mysqli_connect("p:".$host, $username, $password, $new_link);
    }
}

for more infomation:http://us1.php.net/manual/zh/mysqli.construct.php

今天在写程序的时候,发现运算浮点数的时候,总是带着一串随机的小数尾巴,查资料知道,浮点数不能做精确计算,如果要是做精确计算,需要用decimal类型的字段,而不是单精或者双精。

附:http://my.oschina.net/miaoyushun/blog/12684

对于这个问题的发现源于一个计时器程序,先看下这段代码吧。

1
2
3
4
5
6
7
8
9
10
11
12
<?php
$s = gettime();
usleep(10000);
$e = gettime();
var_dump($s);
var_dump($e);
echo $e-$s."\n";
function gettime(){
list($sec, $uses) = explode(' ', microtime());
return $sec + $usec;
}
?>

输出结果为:

1
2
3
float(1296098836.2033)
float(1296098836.2135)
0.010126113891602

有没有发现一个很诡异的现象?被减数和减数整数部分是相同的,小数点后都只是四位,
但是这两个数相减之后得出的结果,小数点后的位数却要大于4。
其实想解释也不难,因为被减数和减数的精度都为14,所以为不造成精度损失,所以结果的精度也必须是14位的。

但出现这种现象的根本原因在哪?

所以我去网上逛了逛,看了些东西后,得到了一些启发。所以又写了一段测试代码:

1
2
3
4
5
6
7
8
<?php
ini_set('precision', 14);
$a = 0.3;
$b = 0.1+0.2;
var_dump($a);
var_dump($b);
$a == $b ? print "equals\n" : print "not equals\n";
?>

输出的结果是:

1
2
3
float(0.3);
float(0.3);
not equals

大家是不是感觉很奇怪,两个变量都是浮点型的,都是0.3,为什么不相等呢?

使用序列化函数serialize查看一下两个数的实际值:

1
2
3
4
<?php
echo serialize(0.3)."\n";
echo serialize(0.1+0.2)."\n";
?>

输出结果:

1
2
d:0.299999999999999988897769753748434595763683319091796875;
d:0.3000000000000000444089209850062616169452667236328125;

你会发现这两个数实际上都不是真正的0.3,为什么这样呢?

其实这个问题要追溯到微机原理(也有可能是计算机组成原理,记不清楚是哪一本书了),
这里面讲了计算机是如何用二进制来存储定点小数。大致是这样的:如果用一个字节的长度来表示一个定点小数,
第一位表示小数的符号,0为正,1为负;后面7位表示小数的值,第2位至第8位的位权分别是1/2,1/4,1/8,1/16,1/32,1/64,1/128,
然后用这些权值的和来表示所有的小数。如何表示0.625呢?

这个有固定的算法:

首先,将小数点左侧的整数部分变换为其二进制形式,处理小数部分的算法是将我们的小数部分乘以基数 2,
记录乘积结果的整数部分,接着将结果的小数部分继续乘以 2,并不断继续该过程。

1
2
3
0.625 × 2  =  1.25    1
0.25  × 2  =  0.5     0
0.5   × 2  =  1       1

当最后的结果为1时,结束这个过程。这时右侧的一列数字就是我们所需的二进制小数部分,即 0.101。
这样,我们就得到了完整的二进制形式 0.101 ,按阶展开:1x1/2+0x1/4+1x1/8=0.5+0.125=0.625。

我们上面先的例子比较特殊,这个数只需要三次运算就能够结束。那会不会有无法结束的情况,不难想象,
很多小数根本不能经过有限次这样的过程而得到结 果(比如最简单的0.1)。

但浮点数尾数域的位数是有限的,为此,浮点数的处理办法是持续该过程直到由此得到的尾数足以填满尾数域,
之后对多余的位进行舍入。也就是说,十进制到二进制的变换也并不能保证总是精确的,而只能是近似值。

事实上,只有很少一部分十进制小数具有精确的二进制浮点数表达。再加上浮点数运算过程中的误差累积,
结果是很多我们看来非常简单的十进制运算在计算机上却往往出人意料。这就是最常见的浮点运算的”不准确”问题。

所以,在计算机里表示的浮点数只是一个近似的数,并不是像表示整数那样精确没有偏差。既然它只是一个约数,那么你用精确的==来比较两位不精确的约数就没有太大意义了。如果一定要比较两个浮点数,可以考虑先转换成字符串,然后再去比较。

我在Linux下使用c编写了一段类似的浮点数比较的代码,结果也是不相等的。实际上在所有的语言里都会存在此问题,
因为这是计算机原理所决定的。但也不排除一些语言做了些后期处理,可以直接比较两个浮点数。

以上仅是个人理解,不保证绝对正确,有错误还请多多谅解。

转自:http://blog.csdn.net/cindy9902/article/details/5886355

以前在用MMM管理multi master 作failover是看到过MMM使用read-only选项来控制对其读写角色的分配,当时尝试过加上这个选项,然后对其进行update,insert操作,发现也是可以的。。所以觉得这个选项没有什么实际意义。。。现在想想当时是用管理员的帐户去执行的,肯定是有super权限的,所以才可以进行update和insert操作。

今天在测试过程中也遇到了read-only的问题,发现写操作因为read-only 这个选项的开启,而不能够成功执行。找了下资料,才了解read-only的真正含义和用法:

阅读全文 »

参考:http://forum.ubuntu.org.cn/viewtopic.php?t=296420

使用udev来实现,udev是linux2.6内核以上的功能,read more:/2013/10/22/some-nifty-udev-rules-and-examples.html

具体实现方法:

如实现U盘自动挂载
Vim 11-add-usb.rules

添加如下内容
ACTION!=”add”,GOTO=”farsight”
KERNEL==”sd[a-z][0-9]”,RUN+=”/sbin/mount-usb.sh %k”
LABEL=”farsight”

这个文件中ACTION后是说明是什么事件,KERNEL后是说明是什么设备比如sda1,mmcblk0p1 等,RUN这个设备插入后去执行哪个程序%k是传入这个程序的参数,这里%k=KERNEL的值也就是sda1等。

在/sbin/下创建mount-usb.sh文件添加如下内容
#!/bin/sh
/bin/mount -t vfat /dev/$1 /tmp
sync

修改文件权限为其添加可执行的权限。

这样就实现了U盘的自动挂载,下面附上U盘的卸载规则文件和sd卡的文件

Usb卸载

11-add-remove.rules
ACTION !=”remove”,GOTO=”farsight”
SUBSYSTEM!=”block”,GOTO=”farsight”
KERNEL==”sd[a-z][0-9]”,RUN+=”/sbin/umount-usb.sh”
LABEL=”farsight”

umount-usb.sh
#!/bin/sh
sync
umount /tmp/

需要注意的是rule文件中的一些符号,比如!=和==,在ubuntu下,如果你的符号有问题,文字的显示颜色会是白色的。

转自:http://blog.csdn.net/scutth/article/details/6980758

其中setresuid()具有最清晰的语法:
setresuid()被执行的条件有:
①当前进程的euid是root
②三个参数,每一个等于原来某个id中的一个
如果满足以上条件的任意一个,setresuid()都可以正常调用,并执行,将
进程的ID设置成对应的ID。
例子:
如果ruid=100,euid=0,suid=300
则setresuid(200,300,100)可以执行,因为原来的euid=0.
如果ruid=100,euid=300,suid=200
则setresuid(200,300,100)也可以执行,因为这三个新的id都是原来id中的某一个。
但是setresuid(100,200,400)就不能执行,因为400不等于原来三个id中的任意一个。

setresuid()有个性质,英文名称是all-or-nothing effect,意思是,如果setresuid()
对某一个ID设置成功了,其他的失败了,比如只改变了ruid,suid和euid都改失败了
那么程序会将ruid改回原来的值,即保证要么三个ID都能成功修改,要么三个都没能修改成功。
PS:FreeBSD和Linux支持setresuid,Solaris不支持setresuid,但有自己的实现方式。

阅读全文 »

debian/ubuntu管理网络连接的有两个东西,图形化的NetworkManager和文字的 ifup/ifdown,如果在 /etc/network/interfaces里设置了网卡信息,那么NetworkManager就不会接管该网卡,如果没有设置NetworkManager默认是会接管网卡的。

当使用 NetworkManager的时候,可以注释掉所有/etc/network/interfaces 里的内容,仅仅保留本地回环网络:
auto lo
iface lo inet loopback
这两句。设置固定ip,可以在NetworkManager图形界面里配置。

关闭NetworkManager
关闭命令:sudo /etc/init.d/network-manager stop
取消开机启动:update-rc.d -f network-manager remove
重启网络:/etc/init.d/networking restart

修改 /etc/network/interfaces 文件,
系统配置部分:本地回环网络。

1
2
auto lo
iface lo inet loopback

有线配置部分:

1
2
3
4
5
6
auto eth0
#iface eth0 inet dhcp # 如果你不想用固定ip的话,推荐用固定ip,这样可以省去请求路由分配的时间
iface eth0 inet static
netmask 255.255.255.0
gateway 192.168.0.1 #gateway 0.0.0.0 # 拨号上网请把 gateway全部设置为0
address 192.168.0.112

无线配置部分:

1
2
3
4
5
6
7
8
9
auto wlan0
iface wlan0 inet static
netmask 255.255.255.0
gateway 192.168.0.1
address 192.168.0.113
pre-up ip link set wlan0 up
pre-up iwconfig wlan0 essid ssid
wpa-ssid TP-Link # 这里的ssid为路由里设置的无线名称
wpa-psk 12345678 # 无线密码

adsl拨号上网:

1
2
3
auto dsl-provider
iface dsl-provider inet ppp # dsl-provider 为之前配置好的拨号名称
provider dsl-provider

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# 默认启动的是 'label linux' 中标记的内核
default linux

# 显示 'boot: ' 提示符。
# 为 '0' 时则不提示,将会直接启动 'default' 参数中指定的内容。
prompt 1

# 在用户输入之前的超时时间,单位为 1/10 秒。
timeout 600

# 显示某个文件的内容,注意文件的路径。默认是在 /tftpboot 目录下。
# 也可以指定位类似 'install/rhel4.4-inst/boot.msg' 这样的,路径+文件名。
display boot.msg

# 按下 'F1' 这样的键后显示的文件。注意路径。默认是 /tftpboot。
# 注:syslinux 官方网站上说目前只能使用 F1-F10。
F1 install/rhel4.4-inst/boot.msg
F2 install/rhel4.4-inst/options.msg
#...
F10 install/rhel4.4-inst/snake.msg

# 'label' 指定你在 'boot:' 提示符下输入的关键字。
# 比如:
#     boot: linux[ENTER]
# 这个会启动 'label linux' 下标记的 kernel 和 initrd.img 文件。
# 这里还定义了其它几个关键字:
#     boot: text
#     boot: ks
#
# kernel 参数指定要启动的内核。同样要注意路径,默认是 /tftpboot 目录。
# append 指定追加给内核的参数,能够在 gurb 里使用的追加给内核的参数,在这里也
#        都可以使用。
label linux
  kernel install/rhel4.4-inst/vmlinuz
  append initrd=install/rhel4.4-inst/initrd.img ramdisk_size=8192

label text
  kernel vmlinuz
  append initrd=install/rhel4.4-inst/initrd.img text ramdisk_size=8192
label expert
  kernel vmlinuz
  append expert initrd=install/rhel4.4-inst/initrd.img ramdisk_size=8192

# 使用 kickstart 安装。
# 可以在 ks 参数后直接指定 kickstart 文件的位置。
# 关于 kickstart 的更多参数和设置,请参考各版本的 RHEL 的 Installation Guide:
# * http://www.redhat.com/docs/manuals/enterprise/
#     Installation Guide --> Advanced Installation and Deployment

label ks basic
  kernel install/rhel4.4-inst/vmlinuz
  append ks=ftp://192.168.10.251/install/rhel4.4_basic.cfg initrd=install/rhel4.4-inst/initrd.img ramdisk_size=8192

label lowres
  kernel vmlinuz
  append initrd=install/rhel4.4-inst/initrd.img lowres ramdisk_size=8192
label local
  localboot 1
label memtest86
  kernel memtest
  append -

网上说的方法都是写一个C程来实现一个中间件,但是貌似好像我看到的文章漏掉了一个比较关键的点,那就是关于S标记位的设置。如果对于s标记位很熟悉的话,那么我觉得文章漏掉了这个点应该不会对自己调试有影响,但是像我这样还不了的人来说,这就是致命的了。s标记位的目的就是在于让一个非程序的拥有者用户临时具有程序拥有者的权限,这一点由于网上的文章没有指明,所以如果只是在普通用户下进行chmod u+s 的话,程序肯定不会执行成功,因为还缺少chown这一步,得先把编译出来的程序的属主修改成root用户,然后这个s标记位才会起到应用的作用,这样程序中的geteuid获取到的值才是root的uid。

最后附上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char** argv)
{
uid_t uid ,euid;

uid = getuid() ;
euid = geteuid();

if(setreuid(euid, uid)) //交换这两个id
perror("setreuid");

system('iptables -L');
return 0;
}
0%