C程序设计语言

Keywords: #C #C语言 #语法
[TOC] 类型、运算符与表达式 char字符型占用一个字节。int整型,反应整数的最自然长度。 常量定义 #define MAXLINE 1000 字符常量’\0’表示值为0的字符,也就是空字符null。字符串内部使用’\0’作为字符串的结尾,因此,存储字符串的物理存储单元数比括在双引号中的字符数多一个。 单引号双引号的区别,’x’是一个整数,其值是字母x在机器字符集中对应的数值;”x”是一个包含一个字符以及一个结束符’\0’的字符数组。 数组和指针 p=&c &用于取一个对象的地址,只能应用内存中的对象。p为指向c的指针。 int *p; p=&x; p现在指向x y=*p;y的值为指针p指向的对象的值。*为间接寻址或者间接引用运算符。 int getint(int *p);参数是一个指针 int getint(&a);使用时用&a取地址 int a[10];定义了一个长度为10的数组,存在相邻内存的地方 int *pa; pa=&a[0];pa指向a[0]的地址 *(pa+i)≡a[i];pa+i指向a[i]的地址 pa≡a;数组名代表数组第一个元素的地址 a[i]≡*(a+i); &a[i]≡a+i; 把数组名传给一个函数时,实际传递的是数组第一个元素的地址。 int strlen(char *s)等价于int strlen(char s[]) 字符串常量是一个字符数组(char a[]),字符数组以”结尾,占有的存储单元数比双引号内的大1 char *p; p=”a man”;把该字符的指针赋值给p char a[10];定义一个字符串,长度为10 char a[]; 结构 struct point { //分别是引入结构申明,结构标记 int x; //成员 int y; }; struct {…} x,y,z;这个就类似于int x,y,z;这儿前面的部分相当于申明类型是结构,这儿也可以没有结构标记 struct point pt;前面两个代表类型,后面的pt是变量,和上面相比,代替{…}的部分 struct point pt={100,200}; pt.x;用来应用其中的成员x struct point pt(int x, int y) { struct point temp; … return temp; } 函数返回struct point类型数据

位运算

Keywords: #二进制 #位运算 #算法
位运算的用法虽然不多,但是所用之处大多有出神入化的作用。 总结一下常用的场景。 位与运算&,位或运算|,非~,异或运算^ 不使用额外变量交换两个数 int swap(int *x,int *y) { *y = *x^*y; *x = *x^*y; *y = *x^*y; } 都是适用异或运算,原理其实是把临时变量和另外一个数混合起来了。 而且异或运算有两个特点: 一个数亦或本身恒等于0,一个数亦或0等于本身。 所以上面的第二步其实为*x=*x^*x^y=0^*y=y,这样就把数交换了。 同理,第三步y=*y^*x^*y=0^*x=*x。 翻转数组就可以用上面的swap进行。 a»1,向右位移1位等效于a/2,a«1,向左位移等效于a*2 左移右移都丢弃溢出的位并补零,但是右移的时候当为有符号整型时情况有点不同。 在二分查找时这种方法用的多,一般用到的*2或者/2的时候最好用这种方法提升效率。 bitmap 对于查找字符串的重复字符,看代码 bool isUnique2(string s) { int a[8]; memset(a, 0, sizeof(a)); int len = s.length(); for(int i=0; i < len; ++i) { int v = (int)s[i]; int idx = v/32, shift=v%32; if(a[idx] & (1 << shift)) return false; a[idx] |= (1 << shift); } return true; } 这里要注意几点,ascii字符256个,而int为32位4bit,所以需要8个int的数组。这儿类似bitmap。

破解联通HG8346R

Keywords: #破解 #联通
以前用长城,但是因为他是个大内网,我想远程控制家里的CB也做不到,所以换成联通。 装上一看,擦,完全定制版,根本就没有端口映射之类的。 所以参考了一些网上的方法,对路由器进行了破解。 首先需要telnet到路由器,但是貌似没法直接连接,我用mac的telnet试了试,显示refuse。我的固件版本是V3R013C10S112,下了个ONT维修使能工具,使用我的小黑,首先断开光纤,然后连接LAN1到电脑,重启光猫,这时它会亮红灯闪烁显示没光纤了。然后打开软件,启用,直到光猫红灯不闪了,并且亮了一排绿灯,就可以用windows使用telnet了。 命令行里使用telnet会提示找不到程序,还要去控制面板找到程序打开telnet客户端功能。 telnet 192.168.1.1连接到光猫,使用root,admin登陆进去,这时还是没有root权限的。 这时首先备份配置文件,打开tftp软件,然后输入命令 backup cfg by tftp svrip 192.168.1.2 remotefile hw_ctree.xml 可以backup cfg?来查看命令格式,这里的ip是电脑的ip,然后会自动调用tftp备份,备份文件默认在tftp目录中。 这时候需要对导出的xml进行修改,首先需要解密,使用工具,输出为.gz文件,然后解压,打开修改如下部分: <X_HW_WebUserInfoInstance InstanceID="1" Enable="1" Password="XXXXXX" ModifyPasswordFlag="0" UserLevel="0" UserName="user"/> 把UserLevel=”1″修改成0,变成超级管理员权限。 然后把文件打包成.gz文件加密,比如加密成hw_ctree.new.xml 接下来在telnet里su切换到root,这个版本的会提示输入根据某CODE换CODE,要使用su密码生成器。 su进去后,使用shell命令,可以使用?看看有哪些shell可用 这里可以看到restorehwmode.sh,执行这个shell就换回华为默认的界面了。然后exit,reset重启光猫。 重启光猫后,因为没有开始的配置了,他的IP池是从192.168.100.1开始的,所以要把电脑ip设置成192.168.100.2,网关设置成192.168.100.1,然后访问光猫。 这次试用默认密码:telecomadmin/admintelecom,然后去系统里找到配置,导入开始的配置,重启,OK了,现在是破解后的界面了,要把IP重新改成自动获取,这时的地址池又从1.1开始了。可以看到所有的功能都出来了,也可以试用端口转发了。 HG8346R破解套件:ONT组播配置、SU密码计算、配置文件加解密、TFTP

AppServer设计

Keywords: #API
[TOC] RESTful Representational State Transfer,表现层状态转换。 资源指一个互联网的实体,比如一个图片,一篇文章。每个URI代指一个唯一的实体。 表现层指一个实体的呈现形式,比如图片的jpg或者png格式,或者它的缩略图形式,thumb.jpg。这些都不应该在URI中体现,而应该在头信息中。 状态转换,让服务器端进行状态转换,有GET,POST,PUT,DELETE等。 所以在一个URI中不应该体现出和实体无关的东西,比如/1/delete就是不符合的。 版本信息可以放到URI中。 用户登录相关 RESTful最重要的一个设计原则就是,客户端和服务器的交互是无状态的。每次都需要带上身份信息。 传统浏览器使用cookie和session。在APP中,服务器端建立一个映射就行,比如uid5对应3n4tef344nfed,登陆后分配一个token值,使用token值来识别用户。使用HTTPs协议防止token值被截获。 没有HTTPs的情况下,可以使用如下方法加密: 请求test.com/user/info,使用md5(“test.com/user/info&token=daf32da456hfdh”)= C99DC0C22437AC275C08CE4A9708B25A的签名, 然后请求test.com/user/info?userId=5&sign= C99DC0C22437AC275C08CE4A9708B25A, 服务器端收到请求后,用同样的算法算出签名,如果一致就通过。 上面的方法有一个问题,就是可能被人截获后重复提交,所以解决方法是加上时间戳, md5(“test.com/user/info?userId=5&token=daf32da456hfdh&timestamp=1425860757”)= C116161A6F430343B6CECF08562F1371 然后请求test.com/user/info?userId=5&timestamp=1425860757&sign= C116161A6F430343B6CECF08562F1371 这样带上时间戳,时间戳是不能被修改的,否则签名无效, 服务器收到请求后,先检测时间是否符合预期范围内,然后比对签名。 上面的方法在第一次获取token的时候还是有风险,这时可以使用对称加密来解决,AES加密。 上面这是内部接口,一般外部接口还是用Auth2.0.

深入理解计算机系统

Keywords: #I/O #并发 #汇编 #线程 #读书笔记 #进程
[TOC] 计算机系统漫游 信息就是位+上下文。 源程序实际上就是一个由值0和1组成的位(bit)序列,8个位被组织成一组,称为字节。 只由ASCII字符构成的文件称为文本文件,所有其他文件都称为二进制文件。 C语言程序的执行过程包含四个阶段, 预处理——将修改原始C程序,比如把#include的文件插入到程序文本中,由.c变成.i 编译——将C语言翻译成汇编语言,输出.s 汇编——将.s文件翻译成机器指令文件(二进制),也叫可重定位目标程序(relocatable object program),输出.o 链接——比如一个程序里调用了printf函数,而每个C编译器都会提供标准C库中的一个函数,存在于printf.o中,链接器将负责处理这个文件的合并,最终得到的文件是一个可执行目标文件,可以被加载到内存中,由系统执行。 系统的硬件组成 总线携带信息字节并负责在各个部件间传递。通常总线被设计成传送定长的字节块,也就是字(word)。字中的字节数(字长)是一个基本的系统参数。现在大多数机器字长有的是4个字节(32位),有的是8个字节(64位)。 主存是一个临时存储设备,在处理器执行程序时,用来存放程序和程序处理的数据。从物理上来说,主存是由一组动态随机存取存储器(DRAM)芯片组成。从逻辑上来说,存储器是一个线性的字节数组,每个字节都有其唯一的地址(即数组索引),这些地址是从0开始的。 处理器是解释或执行存储在主存中指令的引擎。处理器的核心是一个字长的存储设备(寄存器),称为程序计数器(PC)。在任何时刻,PC都指向主存中的某条机器语言指令(即含有该条指令的地址)。 处理器和主存的数据交互要通过主线速度慢,而通过处理器的高速缓存存储器则快的多,其中L1高速缓存和寄存器一样快,L2通过特殊的总线连接到处理器,比L1的时间长5倍,但是仍比访问主存快5~10倍。甚至还有三级高速缓存L3. 操作系统实现两个功能,1,防止硬件被失控的程序滥用。2,向应用程序提供一种简单一致的机制来控制复杂的低级硬件设备。操作系统通过几个基本抽象概念(进程、虚拟存储器和文件)来实现这两个功能。 文件是对I/O设备的抽象, 虚拟存储器是对主存和I/O设备的抽象 进程则是对处理器、主存、I/O设备的抽象 进程是操作系统对一个正在运行的程序的一种抽象。 一个CPU看上去像是在并发得执行多个进程,这是通过处理器在进程间切换实现的,这种机制叫做上下文切换。 操作系统保持跟踪进程运行所需的所有状态信息。这种状态也就是上下文。 虽然我们认为一个进程只有单一的控制流,但是进程实际上可以由多个成为线程的执行单元组成。每个线程都运行在进程的上下文中。 虚拟存储器是一个抽象概念,它让每个进程都以为自己在独占地使用主存。每个进程看到的是一致的存储器,称为虚拟地址空间。地址是下往上增大的。 文件就是字节序列。 信息的表示和处理 大多数的计算机使用八位的块,或者字节,作为最小的可寻址的存储器单元。 机器级别程序将存储器视为一个非常大的字节数组,称为虚拟存储器。存储器的每个字节都由唯一的数字来标示,称为他的地址,所有可能地址的集合称为虚拟地址空间。 十六进制(hex)使用0-9A-F来表示,C语言中,用0x或0X开头的数字常量来表示,比如0XFA1D37B。一个字节的值域从00~FF 0 1 2 …… F 0000 0001 0010 1111 16进制转2进制,每个数字转成2进制,比如0X173A4C 000101110011101001001100 2进制转16进制,每四位一组,如果不是4的倍数,最左边一组可以前面用0补位。 2^n的二进制表示就是1的后面n个0. 每个计算机都由一个字长(word size),指明整数和指针数据的标称大小。因为虚拟地址就是以字来编码的,所以字长决定了虚拟地址空间的最大大小。 C的数据类型char表示一个单独的字节。大多多字节对象都被存储为连续的字节序列,对象的地址为所使用字节中最小的地址。 C中的字符串被编码为一个以null字符结尾的字符数组。每个字符都由某个标准编码来表示,最常见的为ASCII字符码。 程序的机器级表示 GCC C语言编译器以汇编代码的形式产生输出,汇编代码是机器代码的文本表示。GCC调用汇编器和链接器,从而根据汇编代码生成可执行的机器代码。 本章基于两种相关的机器语言:Intel IA32(Intel Architecture 32bit Intel 32位体系结构)和x86-64,后者是前者在64位机器上运行的扩展。 Intel处理器系列俗称x86. 计算机系统使用了多种不同形式的抽象,有两种尤为重要: 1,机器级程序的格式和行为,定义为指令集体系结构(ISA),它定义了处理器状态、指令的格式,以及每条指令对状态的影响。大多数ISA,包括IA32和x86-64,将程序的行为描述成好像每条指令都是按顺序执行的,一条接一条。而其实它们是并发地执行,但是可以采取措施保证整体行为和ISA指定的顺序执行完全一致。 2,机器级程序使用的存储器地址是虚拟地址,提供的存储器模型看上去是一个非常大的字节数组。 IA32机器代码和C代码差别很大,比如一些处理器状态是可见的: 程序计数器,通常称为PC,用%eip表示,指示将要执行的下一条指令在存储器中的地址。 整数寄存器文件包含8个命名的位置,分别存储32位的值。主要用来存地址、整数、某些程序状态、临时数据如过程的局部变量和函数的返回值。 条件码寄存器,保存着最近执行的算术或逻辑指令的状态信息。 一组浮点寄存器存放浮点数据。 程序存储器program memory包含:程序的可执行机器代码,操作系统需要的信息用来管理过程调用和返回的运行时栈以及用户分配的存储器块。 程序存储器用虚拟地址来寻址。在任意给定的时刻,只认为有限的一部分虚拟地址是合法的(即使32位系统可以寻址4G地址范围,但通常一个程序只会访问几兆字节)。操作系统负责管理虚拟地址空间,将虚拟地址翻译成实际处理器存储器processor memory中的物理地址。

安装软件程序

Keywords: #Linux
[TOC] 包管理系统 Package Management System,PMS 每个主要的linux发行版都利用包管理系统来管理软件和库 PMS通过数据库来记录安装了什么软件包,每个包安装了什么软件,每个软件包的版本 软件包存储在服务器上(repository 库),通过本地的PMS来访问服务器上的库来实现安装搜索更新 目前主要的PMS基础工具是dpkg和rpm 基于Debian的发行版比如Ubuntu等使用dpkg 基于Red Hat的发行版比如Fedora,openSUSE,centOS使用rpm 基于Debian aptitude命令进入全屏模式,查看当前安装了什么软件 dpkg -L vim 可以显示当前软件关联的所有文件列表 dpkg –search /usr/lib/php5 这样可以显示这个软件属于哪个软件包 aptitude search mysql 搜索软件包 aptitude install mysql-server 安装软件包 aptitude safe-upgrade 更新软件包而且会检查包与包之间的依赖关系 aptitude remove mysql-server只删除软件不删除数据和配置文件 aptitude purge mysql-server 彻底删除软件 aptitude库位置存储在/etc/apt/sources.list中,推荐的是中国科学院的库 基于Red Hat yum list installed 列出已安装的包 yum install mysql-server 安装软件 手动下载rpm并yum安装 yum localinstall mysql-server.rpm yum list updates 列出可用更新 yum update mysql-server 更新软件 yum update 更新所有可更新的 yum remove mysql-server 卸载软件保留配置文件和数据文件

Shell script编程

Keywords: #bash #shell
[TOC] 变量 显示变量 echo $PATH echo $variable echo ${HOME} 设置变量,注意单引双引的区别 name=luca name="luca use $LANG" name=luca\ use\ $LANG #使用\转义空格 version=$(uname -r) version=`uname -r` PATH=${PATH}":/home/bin" name=${name}ly 如果变量需要在子进程使用,需要export来使变量变成环境变量 export PATH 查看当前shell环境中的环境变量 env export 查看环境变量和自定义变量的所有变量 set $本身是个变量,代表当前shell线程代号,echo $$ $?代表上个执行命令的回传码,exit 0 #脚本返回0为成功 declare来实现更改变量类型、属性等 declare -i sum=1+2+3 #将变量定义为整数,不申明会当做字符串输出 sum=$((1+2+3)) #这样也能计算 sum=$[1+2+3] #这样也能计算 declare -a ary #将ary定义为数组类型 declare -x sum #将sum定义为环境变量 declare +x sum #将sum从环境变量移除 declare -r sum #将sum定义为只读 delcare -p sum #列出sum的类型 变量内容的替换和删除 删除 ${variable#a*b} variable代表变量不加$,#代表从前面开始删,且去最少匹配,*为0到多个匹配,ab代表从a字符删到b字符,包括ab在内都删 ${variable##a*b} ##代表按最多的删 ${variable%a*b} %代表从后面开始删,ab的次序和变量中的次序不变,从a删到b ${variable%%a*b} %%表示按最多的删,删到最后用a* 替换

习惯Mac

Keywords: #MBP
开发环境 使用iterm2替代系统自带的命令行工具。 使用homebrew作为软件管理工具,安装: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 使用: brew install wget 其他: brew update 更新brew brew upgrade 更新所有package brew list 查看安装列表 *注:首先要安装xcode才能编译 使用zsh和oh my zsh shell是linux/unix的一个壳,负责外部与linux内核的交互,接受外部的命令把它转化为内核能懂的语言,然后将接收到的内容返回给外部。zsh是其中的一个shell。默认是bash。oh my zsh是一个能让人快速上手的zsh项目。 设置当前用户使用 zsh:chsh -s /bin/zsh 安装oh my zsh wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | sh 更多zsh使用可以看: 终极 Shell——ZSH iterm2免登陆 其实就是利用ssh免登陆,首先在mac生成公钥,ssh-keygen -t rsa 然后把.ssh/id_rsa.pub传到远程服务器的.ssh/authorized_keys中,可追加 然后编辑.ssh/config Host ifsite Hostname 101.200.172.176 Port 22 User root IdentityFile ~/.ssh/id_rsa 然后直接ssh ifsite就可以免登陆了 选中即复制,使用command+f查找,然后按tab或者tab+shift来选中右边或者左边的内容,即复制了

高性能MYSQL读书笔记

Keywords: #MYSQL #数据库
[TOC] 结构和历史 隔离级别有四种: READ UNCOMMITTED(未提交读),同事务中某个语句的修改,即使没有提交,对其他事务也是可见的。这个也叫脏读。 READ COMMITTED(提交读),另一个事务只能读到该事务已经提交的修改,是大多数据库默认的隔离级别。但是有下列问题,一个事务中两次读取同一个数据,由于这个数据可能被另一个事务提交了两次,所以会出现两次不同的结果,所以这个级别又叫做不可重复读。这里的不一样的数据包括虚读(两次结果不同)和幻读(出现新的或者缺少了某数据)。 REPEATABLE READ(可重复读),这个级别不允许脏读和不可重复读,比如MYSQL中通过MVCC来实现解决幻读问题。 SERIALIABLE(可串行化),这儿实现了读锁,级别最高。 显示和隐式锁定:事务执行中,随时可以执行锁定,锁只有在COMMIT或ROLLBACK的时候才释放,而且所有的锁是同时释放的。这些锁定都是隐式锁定。也可以通过特定语句显式锁定,比如SELECT … LOCK IN SHARE MODE等。 MVCC(多版本并发控制):通过保存数据在某个时间点的快照来实现。在INNODB中通过每行记录后保存两个隐藏的列,一个保存行的创建时间,一个保存行的过期(删除)时间,这儿的保存不是时间而是系统版本号,随着事务的数量增加而增加版本号。 SELECT:只找版本号早于当前事务版本的数据,删除版本要大于当前版本号。 INSERT:插入时保存当前版本号为行版本号。 DELETE:为删除的每行保存当前版本号为行的删除标示。 UPDATE:先为插入的行保存版本号,同时保存当前版本号为行删除标示。 INNODB通过MVCC来支持高并发,通过间隙锁来防止幻读。 MYISAM支持读取的时候插入(并发插入),支持延迟更新索引键(Delayed Key Write),先写内容最后才更新索引,需要指定DELAY_KEY_WRITE。 SCHEMA与数据类型优化 避免使用NULL。 整数类型中,TINYINT使用8位存储空间,BIGINT为64位,一般做SIMHASH选择64位做特征值应该是基于这个,转成16进制有16位。其中指定的宽度只在命令行中展示时起作用。 实数类型中,DECIMAL用于存储精确的小数,比如货币。 VARCHAR比定长CHAR更省空间,因为它只需要使用必要的空间,但是其需要使用1或者2个额外字节用来记录字符串的长度。但是在update的时候,容易造成碎片。 CHAR是定长的,MYSQL根据定义字符串的长度分配空间,而且其会删除所有末尾空格。比如存”STRING “的时候,末尾的空格会被删除。 VARCHAR(5)和VARCHAR(100)存同一个字符虽然空间开销相同,但是在存的时候会消耗更多内存,还有在使用临时表的时候也会比较糟糕。 BLOB和TEXT是为存储很大数据而设计的,分别以二进制和字符方式存储。TEXT是SMALLTEXT的同义词,BLOB也是。 ENUM类型存储是非常紧凑,其实际存储为整数。 BIT可以在一列中存储一个或多个0/1值,最大长度为64。问题是存进去是二进制,但是展示出来却是十进制的。 计数器表的优化,对于单表的a+1操作可能受到锁的影响,可以通过创建100行数据,然后随机选取一行写,取的时候使用SUM(a)进行查询。 高效ALTER TABLE,修改表结构涉及到不需要改变数据只要改frm文件的时候,可以使用语句ALTER COLUMN来操作。 还有替换frm的高效方法,首先create table like来建立新表,修改新表结构,对旧表数据执行锁定”FLUSH TABLES WITH READ LOCK;” 执行系统命令,mv new.frm a.frm之类,记得备份。 UNLOCK TABLES; 高效载入数据到MyISAM表,可以暂时禁用索引。 ALTER TABLE tab DISABLE KEYS; ALTER TABLE tab ENABLE KEYS; 但是DISABLE KEYS只对非唯一索引有效。 创建高性能的索引 B-Tree索引,其意味着所有的值都是按照顺序存储的,并且每一个叶子页到根的距离都相等。 B-Tree对索引列是顺序存储的,所以很适合查找范围数据。 缺点是必须按照索引从最左列开始查找,否则无法使用索引。 R-Tree(空间数据索引),MyISAM表支持空间索引,可以用作地理数据存储。

数据结构温习

[TOC] 哈希表 简介:哈希表(Hash table,散列表),是根据K-V而直接访问的一种数据结构。 两种类型的哈希表: 链式哈希表,通过每个桶附加链表来解决哈希冲突。 **开地址哈希表,**通过探查这个表,直到找到一个可以放置元素的槽。具体方法有线性探查、双散列。 哈希函数: 1,取余,除整取余。 2,处理字符串的哈希函数,ELFhash算法,通过一系列位操作将键强制转换为整数。 int ELFhash(char*key) { unsigned long h=0; while(*key) { h = (h &lt;&lt; 4) + *key++; unsigned long g = h & 0xF0000000L; if(g) h ^= g &gt;&gt; 24; h &= ~g; } return h % MOD; }