SQUID TCP命中率解释

#cat access.log|gawk ‘{print $4}’|sort|uniq -c|sort -nr
9568 TCP_IMS_HIT/304
6313 TCP_HIT/200
2133 TCP_MISS/200
1568 TCP_MISS/206
587 TCP_MEM_HIT/200
531 TCP_MISS/304
207 TCP_REFRESH_HIT/200
152 TCP_REFRESH_HIT/304
86 TCP_NEGATIVE_HIT/404
69 TCP_MISS/404
9 TCP_MISS/000
4 TCP_MISS/503
1 TCP_REFRESH_MISS/000
1 TCP_DENIED/400

可以使用上面的方法,大约的分析一下命令中比。什么意思就看下面的详解.
#cat /var/log/squid/access.log |grep TCP_MEM_HIT
如果看到很多的TCP_MEM_HIT ,这表明该文件是从内存缓存读取的,squid已经起作用了!你再用浏览器打开该文件,应该是快如闪电了。。呵呵,大功告成了!还有其他类型的HIT,如TCP_HIT等等,这些是从磁盘读取的,我觉得加速的意义不大,只不过缓解了apache的压力而已。

相应于HTTP请求,下列标签可能出现在access.log文件的第四个域。

TCP_HIT
Squid发现请求资源的貌似新鲜的拷贝,并将其立即发送到客户端。

TCP_MISS
Squid没有请求资源的cache拷贝。

TCP_REFERSH_HIT
Squid发现请求资源的貌似陈旧的拷贝,并发送确认请求到原始服务器。原始服务器返回304(未修改)响应,指示squid的拷贝仍旧是新鲜的。

TCP_REF_FAIL_HIT
Squid发现请求资源的貌似陈旧的拷贝,并发送确认请求到原始服务器。然而,原始服务器响应失败,或者返回的响应Squid不能理解。在此情形下,squid发送现有cache拷贝(很可能是陈旧的)到客户端。

TCP_REFRESH_MISS
Squid发现请求资源的貌似陈旧的拷贝,并发送确认请求到原始服务器。原始服务器响应新的内容,指示这个cache拷贝确实是陈旧的。

TCP_CLIENT_REFRESH_MISS
Squid发现了请求资源的拷贝,但客户端的请求包含了Cache-Control: no-cache指令。Squid转发客户端的请求到原始服务器,强迫cache确认。

TCP_IMS_HIT
客户端发送确认请求,Squid发现更近来的、貌似新鲜的请求资源的拷贝。Squid发送更新的内容到客户端,而不联系原始服务器。

TCP_SWAPFAIL_MISS
Squid发现请求资源的有效拷贝,但从磁盘装载它失败。这时squid发送请求到原始服务器,就如同这是个cache丢失一样。

TCP_NEGATIVE_HIT
在对原始服务器的请求导致HTTP错误时,Squid也会cache这个响应。在短时间内对这些资源的重复请求,导致了否命中。 negative_ttl指令控制这些错误被cache的时间数量。请注意这些错误只在内存cache,不会写往磁盘。下列HTTP状态码可能导致否定 cache(也遵循于其他约束): 204, 305, 400, 403, 404, 405, 414, 500, 501, 502, 503, 504。

TCP_MEM_HIT
Squid在内存cache里发现请求资源的有效拷贝,并将其立即发送到客户端。注意这点并非精确的呈现了所有从内存服务的响应。例如,某些cache在

资源来源:
http://www.wendangku.net/doc/0d7c5bb15ef7ba0d4b733b48.html

发表在 article | SQUID TCP命中率解释已关闭评论

Java 8 Stream API

.
https://blog.csdn.net/hxhaaj/article/details/80725857
https://www.cnblogs.com/jimoer/p/10995574.html

如果你正在使用 Java 编程,那么可以使用 Java 8 Stream API 来做进一步的类比。考虑如下等价概念:

TABLE          : Stream>
 SELECT         : map() 
 DISTINCT       : distinct()
 JOIN           : flatMap()
 WHERE / HAVING : filter()
 GROUP BY       : collect()
 ORDER BY       : sorted()
 UNION ALL      : concat()

在 Java 8 中,“一切都是流”(至少在你开始使用流时是这样)。无论如何转换流,例如,使用 map() 或 filter() 转换,结果类型始终都是流。

发表在 java | Java 8 Stream API已关闭评论

mysql主从一致性校验工具-pt

一、环境

1、系统环境

系统IP主机名说明server_id
centos6.7MasterIPmaster数据库:主177 
centos6.7SlaveIPslave数据库:从148

2、软件环境

软件版本安装方式说明
pt工具3.0.4编译安装这是一个综合工具包,包含很多pt命令
mysql数据库5.6.37yum安装主从环境

3、需要用到库

库名表名用途
 perconachecksums 存储pt命令监测的结果,第一次执行检测命令时会自己创建 修复工具修复的时候会读取该表

#本表格也可以自己创建,在使用pt工具的时候指定库表名字,详见下面的参数解释。

注意:自建库表测试尚未通过。

二、为什么要做主从一致性监测

1、主从复制是基于binlog的逻辑复制,难免出现复制数据不一致的风险

2、这个风险不但会引起用户数据访问前后不一致的风险

3、而且会导致后续复制出现1032、1062错误进而引起复制架构停滞的隐患

4、为了及时发现并解决这个问题

5、我们需要定期或不定期地开展主从复制数据一致性的校验和修复工作

三、主从一致性监测原理

四、pt工具监测

用到的命令:

1、pt-table-check       #监测主从一致

2、pt-table-sync         #修复主从一致

mysql主从一致性校验,基于pt工具进行。

#限制及问题

1、在检查阶段,超过1000行的数据,如果没有设定索引或者主键,则报错,该表会跳过检查。

2、在修复阶段,如果表没有设置主键或索引,则修复报错,可以手动进行修复。

3、监测是基于块进行的,如果mysql表的数据没有进行分块,那么当表过大时,会造成监测一段时间后发现没有问题会跳过改表。

4、当数据库两个数据不一致,但是checksum检测一致时,没有比对出不一致。

主库和从库账号一致,密码不一致发现了这种问题。

原因:对于修改密码的操作,chencksum的值并没有发生变化。

五、安装pt工具

最好所有主库从库都安装

1、安装依赖

yum install perl-IO-Socket-SSL perl-DBD-MySQL perl-Time-HiRes perl perl-DBI -y

yum install perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker -y

2、下载安装包

1、官网下载

3、安装

 tar xzvf percona-toolkit-3.0.4_x86_64.tar.gz

 cd percona-toolkit-3.0.4

perl Makefile.PL   --安装到非默认路径PREFIX=${HOME}

 make

 make test

 make install

六、pt工具常用命令

1、创建监测账号

grant all on *.*  to   'zxfly_check'@'192.168.22.% ' identified by 'zxfly';

flush privileges;

2、监控用的表为:percona.checksum该表会自动创建。

监测:

#指定库名

pt-table-checksum --databases zxfly -u'zxfly' -p'zxfly' -hMasterIP -P3306 2>/logs/pt_error.log 1>/logs/pt_info.log

#不指定库,监测所有数据库(除information_schema、percona、performance_schema库)

pt-table-checksum --quiet -u'zxfly' -p'zxfly' -hMasterIP -P3306 2>/logs/pt_error.log 1>/logs/pt_info.log

pt-table-checksum --replicate-check-only -u'zxfly' -p'zxfly' -hMasterIP -P3306

打印修复sql:指定库表

pt-table-sync  --databases=dataname --tables=table1,table2 h=MasterIP,u=zxfly,p=zxfly h=SlaveIP,u=zxfly,p=zxfly --charset=utf8 --print 

修复:

pt-table-sync  --databases=dataname --tables=table1,table2 h=MasterIP,u=zxfly,p=zxfly h=SlaveIP,u=zxfly,p=zxfly --charset=utf8 --exec

七、pt工具常用参数

1、pt-table-checksum

参数参数说明备注
--[no]check-replication-filters不检查复制过滤器,建议启用。后面可以用--databases来指定需要检查的数据库。当前环境不需要该参数,默认开启
--no-check-binlog-format不检查复制的binlog模式,要是binlog模式是ROW,则会报错。默认是监测,使用默认值,如果添加该参数可能导致diff不出来
--replicate-check-only只显示不同步的信息。 开启这个,可以减少输出并且显示不一致的从库主机名 不过这个只是显示已经检测过的不一致信息,并不能显示当前的。
--replicate=把checksum的信息写入到指定表中,建议直接写到被检查的数据库当中。不需要指定默认会创建percona库下checksum表
-h -u -p -PmasterIP 监测账号 密码 端口 
--databases=指定需要被检查的数据库,多个则用逗号隔开。 
--tables=指定需要被检查的表,多个用逗号隔开 
--recursion-method指定监测从库的模式,默认使用processlist,也可以指定dsn 多个从库可以这样指定。--recursion-method=dsn=h=host,D=pt,t=dsns D 库名 t 表名
--quiet安静模式,最小化打印,纸打印错误行与--replicate-check-only类似,但不显示从库信息

dsn库表结构及用法为:

  1. CREATE TABLE `dsns` ( `id` int(11) NOT NULL AUTO_INCREMENT, `parent_id` int(11) DEFAULT NULL, `dsn` varchar(255) NOT NULL, PRIMARY KEY (`id`) );
  2. -- 写入从库信息
  3.  INSERT INTO dsns (parent_id,dsn) values(1, "h=replica_host,u=checksums,p=password,P=3306"); 
  4. -- 如果有多个从库,就插入多条记录. 
  5. -- 也可以按如下简写
  6. INSERT INTO dsns (parent_id,dsn) values(1, "h=replica_host");

2、pt-table-sync

参数参数说明备注
--replicate=指定通过pt-table-checksum得到的表默认会创建percona库下checksum表时不需要指定
--databases=指定执行同步的数据库在只修复指定的库时使用
--tables=指定需要被修复的表,多个用逗号隔开 
--sync-to-master指定一个DSN,即从的IP会通过show processlist或show slave status 去自动的找主。报错找不到主库时使用
h= u= p=服务器地址,账号,密码命令里有2个ip,第一次出现的是Master的地址,第2次是Slave的地址。
--print打印修复的sql语句只打印不执行。
--exec 或 --execute执行修复 
--algorithms=c指定修复算法 default Chunk,Nibble,GroupBy,Stream 在报错算法问题的时候需要指定算法
--charset=指定默认字符集如果数据中包含中文不指定次字符集的话修复不成功

3、输出信息解释

TS :完成检查的时间。
ERRORS :检查时候发生错误和警告的数量。
DIFFS :0表示一致,1表示不一致。当指定--no-replicate-check时,会一直为0,当指定--replicate-check-only会显示不同的信息。
ROWS :表的行数。
CHUNKS :被划分到表中的块的数目。
SKIPPED :由于错误或警告或过大,则跳过块的数目。
TIME :执行的时间。
TABLE :被检查的表名。

八、pt工具常见报错信息

1、监测报错(找不到从库,使用--recursion-method指定模式)

Diffs cannot be detected because no slaves were found. Please read the --recursion-method documentation for information.

2、binlog模式问题(由于指定为row行复制造成 使用--no-check-binlog-format跳过监测,不过这样有可能监测不出来主从不一致的信息,row行模式对于主从来说不需要进行主从监测)

Replica centos-1 has binlog_format ROW which could cause pt-table-checksum to break replication. Please read "Replicas using row-based replication" in the LIMITATIONS section of the tool's documentation.  If you understand the risks, specify --no-check-binlog-format to disable this check.

3、没有索引或主键导致的,在数据较少的时候(低于1000行,没有测试出该信息,超过1000行会报错)

Cannot checksum table test.t: There is no good index and the table is oversized. at ./pt-table-checksum line 6370.

4、等待信息,已检测的百分比,这是因为设置了主键但是没有索引导致没有分块且表过大造成。

Checksumming database.table:  27% 01:17 remain

九、对多个库所有数据进行监测结果

pt-table-checksum监测数据库结果:

数据大小监测花费时间监测报错的表原因
93G30m28.523s 4个 #字符集bug(工具自带,无法解决) 正式平台这些表都没有
  1个 未监测到(中文表名监测不到) 正式平台无此表
  1个没有主键或者索引(数据条数:132835)

十、pt修复工具pt-table-sync遇到的问题

在使用pt-table-checksum进行检测后,发现主从不一致的情况后可以使用pt-table-sync工具进行修复操作。

其原理为:基于pt-table-checksum监测的结果进行检查并生成修复语句去修复从库中的数据。

遇到的报错:

1、修复时候没有任何提示,但是修复报错。使用–print打印修复语句发现又乱码。

处理方法:查看表的字符集,通过--charset=命令指定默认字符集

2、报错:Failed to prepare TableSyncChunk plugin: Cannot chunk table `zxfly_zxfly1`.`mongo_task_data` using the character column guid, most likely because all values start with the same character. This table must be synced separately by specifying a list of --algorithms without the Chunk algorithm at /usr/local/bin/pt-table-sync line 4088.  while doing table on 192.168.0.177

原因是在默认的算法中,要保证主键字段的数据前一位有不一样字符出现,而该表的主键数据第一个字符是一样的。

解决办法:

使用--algorithms=参数指定算法,当然这种应该最好分库分表进行恢复。

6、修复报错(原因:没有唯一索引或主键导致的,1000以内的,1000行以上没有索引或主键在监测时就会跳过。)

Can't make changes on the master because no unique index exists at /usr/local/bin/pt-table-sync line 10591.

.

发表在 db | mysql主从一致性校验工具-pt已关闭评论

jFileServer examples

用户使用 (Token 授权)
上传: POST: /file/upload
bucket={xxx}
token={xxx}
path={xxx} // 可选项,不输入则自动生成路径

访问: GET: /file/get?path={xxx}&token={xxx}&download=0&downname={xxx}
download: 为可选项,设为2时以内联文档打开(一般用于预览),设为1时以资源下载方式处理,不设置或为0时则是以浏览器默认方式处理
downname: 为可选项,download = 1 时,文件下载的名称,不设置则以默认路径名
fsatoken: 可选项,会话授权访问标识,从cookie获取

===============================================

控制使用 (Basic Auth 授权)

POST: /control/delete
path={xxx}
POST: /control/upload
bucket={xxx}
path={xxx} // 可选项,不输入则自动生成路径
GET: /control/getaccesstoken?path={xxx},{xxx},{xxx},{xxx}&fsatoken={xxx}&ttl={xxx}
GET: /control/getuploadtoken?bucket={xxx},{xxx},{xxx},{xxx}
ttl: 可选项,授权超时时间,默认由服务配置定义
fsatoken: 可选项,会话授权标识, fsatoken存储于客户cookie, 同一fsatoken的token授权允许多次访问,随会话失效而失效

================================================

路径构成:
物理存储路径 + 桶名 + 存储路径(必需以 /为开始)
/file/ + mybucket + /2017/00/11.jpg
/file/ + mybucket + /af/ce/head.jpg

存储路径:

/file/mybucket/2017/00/11.jpg
/file/mybucket/af/ce/head.jpg

访问地址:
私桶下载
http://file.example.com/a/{bucket}{path}?token={xxx}&download=1
私桶访问
http://file.example.com/a/{bucket}{path}?token={xxx}
公桶下载
http://file.example.com/a/{bucket}{path}?download=1
公桶访问
http://file.example.com/a/{bucket}{path}

================================================

授权
默认情况下,均为token授权,通过配置桶授权可允许设置为开放访问,级别到 桶
默认公开桶为 p (public的简写)

.

发表在 technologys | jFileServer examples已关闭评论

为什么redis集群的最大槽数是16384个?

在redis节点发送心跳包时需要把所有的槽放到这个心跳包里,以便让节点知道当前集群信息,16384=16k,在发送心跳包时使用char进行bitmap压缩后是2k(2 * 8 (8 bit) * 1024(1k) = 2K),也就是说使用2k的空间创建了16k的槽数。

虽然使用CRC16算法最多可以分配65535(2^16-1)个槽位,65535=65k,压缩后就是8k(8 * 8 (8 bit) * 1024(1k) = 8K),也就是说需要需要8k的心跳包,作者认为这样做不太值得;并且一般情况下一个redis集群不会有超过1000个master节点,所以16k的槽位是个比较合适的选择。

.

发表在 article | 为什么redis集群的最大槽数是16384个?已关闭评论

C# DateTime 日期格式化

在C#中DateTime是一个包含日期、时间的类型,此类型通过ToString()转换为字符串时,可根据传入给Tostring()的参数转换为多种字符串格式。

目录

1. 分类

2. 制式类型

3. 自定义格式类型 

1. 分类

DateTime调用ToString()传入的参数可分为制式和自定义两种:

1) 制式:系统自带的,转入特定的单个字符就可转换为系统已设定好的格式。

2) 自定义:自由组合日期代码(y、M、d、h、m、s、f)来展示丰富的日期格式。

2. 制式类型

说明:转入特定的单个字符就可转换为系统已设定好的格式。

2.1 格式来源

在Windows系统中的区域和语言(位置:控制面板 → 区域和语言)选项中可设置日期和时间的格式。

可设置的分类有:短日期、长日期、短时间、长时间等。

调用ToString()进行转换时,许多转换方式都是通过上面的4个分类进行组合。

2.2 符号对照表

2.2.1 环境

.net版本:4.0

系统版本:Win7

格式信息

2.2.2 对照表

符号 语法 示例(2016-05-09 13:09:55:2350) 格式说明
y DateTime.Now.ToString() 2016/5/9 13:09:55 短日期 长时间
d DateTime.Now.ToString("d") 2016/5/9 短日期
D DateTime.Now.ToString("D") 2016年5月9日 长日期
f DateTime.Now.ToString("f") 2016年5月9日 13:09 长日期 短时间
F DateTime.Now.ToString("F") 2016年5月9日 13:09:55 长日期 长时间
g DateTime.Now.ToString("g") 2016/5/9 13:09 短日期 短时间
G DateTime.Now.ToString("G")  2016/5/9 13:09:55 短日期 长时间
t DateTime.Now.ToString("t") 13:09 短时间
T DateTime.Now.ToString("T") 13:09:55 长时间
u DateTime.Now.ToString("u") 2016-05-09 13:09:55Z  
U DateTime.Now.ToString("U") 2016年5月9日 5:09:55 本初子午线的长日期和长时间
m DateTime.Now.ToString("m") 5月9日  
M DateTime.Now.ToString("M") 5月9日  
r DateTime.Now.ToString("r") Mon, 09 May 2016 13:09:55 GMT  
R DateTime.Now.ToString("R") Mon, 09 May 2016 13:09:55 GMT  
y DateTime.Now.ToString("y") 2016年5月  
Y DateTime.Now.ToString("Y") 2016年5月  
o DateTime.Now.ToString("o") 2016-05-09T13:09:55.2350000  
O DateTime.Now.ToString("O") 2016-05-09T13:09:55.2350000         
s DateTime.Now.ToString("s") 2016-05-09T13:09:55  

2.3 示例图

2.4 win2003版本 

在Win2003默认中的无字符、d、g、G格式中会用'-'符号替代'/'符号(短日期格式为:yyyy-m-d)。

3. 自定义格式类型

开发人员可通过英文字符(y、M、d、h、m、s、f) 分别代替(年、月、日、时、分、秒、毫秒)来自由组合日期时间格式。

3.1 符号对照表

.net版本:4.0

系统版本:Win7

符号 说明
语法 示例(2016-05-09 13:09:55:2350)
yy年份后两位DateTime.Now.ToString("yy")DateTime.Now.ToString("yy"); // => 16
yyyy4位年份DateTime.Now.ToString("yyyy")DateTime.Now.ToString("yyyy"); // => 2016
MM两位月份;单数月份前面用0填充DateTime.Now.ToString("MM")DateTime.Now.ToString("MM"); // => 05
dd日数DateTime.Now.ToString("dd")DateTime.Now.ToString("dd"); // => 09
ddd周几DateTime.Now.ToString("ddd")DateTime.Now.ToString("ddd"); // => 周一
dddd星期几DateTime.Now.ToString("dddd")DateTime.Now.ToString("dddd"); // => 星期一
hh12小时制的小时数DateTime.Now.ToString("hh") DateTime.Now.ToString("hh"); // => 01
HH24小时制的小时数DateTime.Now.ToString("HH")DateTime.Now.ToString("HH"); // => 13
mm分钟数DateTime.Now.ToString("mm")DateTime.Now.ToString("mm"); // => 09
ss秒数DateTime.Now.ToString("ss")DateTime.Now.ToString("ss"); // => 55
ff毫秒数前2位DateTime.Now.ToString("ff")DateTime.Now.ToString("ff"); // => 23
fff毫秒数前3位DateTime.Now.ToString("fff")DateTime.Now.ToString("fff"); // => 235
ffff毫秒数前4位DateTime.Now.ToString("ffff")DateTime.Now.ToString("ffff"); // => 2350
分隔符
可使用分隔符来分隔年月日时分秒。 包含的值可为:-、/、:等非关键字符 DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff"); // => 2016-05-09 13:09:55:2350 DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss:ffff"); // => 2016/05/09 13:09:55:2350 DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss:ffff dddd"); // => 2016/05/09 13:09:55:2350 星期一

3.2 示例图

.

.

C# DateTime 日期格式化已关闭评论

windows 定时清理指定目录文件bat

eg:

删除E:\original目录下(包括子目录)所有以.png为后缀的、最后修改时间为7天前的文件

指令:

 forfiles /p E:\original /s /m *.png -d -7 /c "cmd /c del /q /f @path"

解释:

/p - 指定的路径
/s - 包括子目录
/m - 查找的文件名,支持通配符*。
/d - 指定日期,有绝对日期和相对日期, 此处-7指当前日期 的7天前

/c - 运行的命令行 表示为每个文件执行的命令。命令字符串应该
用双引号括起来。

                    默认命令是 "cmd /c echo @file"。下列变量
                    可以用在命令字符串中:
                    @file    - 返回文件名。
                    @fname   - 返回不带扩展名的文件名。
                    @ext     - 只返回文件的扩展。
                    @path    - 返回文件的完整路径。
                    @relpath - 返回文件的相对路径。
                    @isdir   - 如果文件类型是目录,返回 "TRUE";
                               如果是文件,返回 "FALSE"。
                    @fsize   - 以字节为单位返回文件大小。
                    @fdate   - 返回文件上一次修改的日期。
                    @ftime   - 返回文件上一次修改的时间。

版权声明:本文为CSDN博主「pokefade」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_19983129/article/details/73127547

发表在 windows | windows 定时清理指定目录文件bat已关闭评论

mysql中的utf8mb4、utf8mb4_unicode_ci、utf8mb4_general_ci

1.utf8与utf8mb4(utf8 most bytes 4)

  • MySQL 5.5.3之后增加了utfmb4字符编码
  • 支持BMP(Basic Multilingual Plane,基本多文种平面)和补充字符
  • 最多使用四个字节存储字符

utf8mb4是utf8的超集并完全兼容utf8,能够用四个字节存储更多的字符。

标准的UTF-8字符集编码是可以使用1-4个字节去编码21位字符,这几乎包含了世界上所有能看见的语言。
MySQL里面实现的utf8最长使用3个字符,包含了大多数字符但并不是所有。例如emoji和一些不常用的汉字,如“墅”,这些需要四个字节才能编码的就不支持。

2.字符集、连接字符集、排序字符集

utf8mb4对应的排序字符集有utf8mb4_unicode_ci、utf8mb4_general_ci.

utf8mb4_unicode_ci和utf8mb4_general_ci的对比:

  • 准确性:
    • utf8mb4_unicode_ci是基于标准的Unicode来排序和比较,能够在各种语言之间精确排序
    • utf8mb4_general_ci没有实现Unicode排序规则,在遇到某些特殊语言或者字符集,排序结果可能不一致。
    • 但是,在绝大多数情况下,这些特殊字符的顺序并不需要那么精确。
  • 性能
    • utf8mb4_general_ci在比较和排序的时候更快
    • utf8mb4_unicode_ci在特殊情况下,Unicode排序规则为了能够处理特殊字符的情况,实现了略微复杂的排序算法。
    • 但是在绝大多数情况下发,不会发生此类复杂比较。相比选择哪一种collation,使用者更应该关心字符集与排序规则在db里需要统一。

作者:AmyZYX
出处:http://www.cnblogs.com/amyzhu/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

================================================================

UTF-8是使用1~4个字节,一种变长的编码格式,字符编码。mb4即 most bytes 4,使用4个字节来表示完整的UTF-8。

mysql的 utf8 编码最大字符长度为 3 字节,如果遇到 4 字节的宽字符就会插入异常了。三个字节的 UTF-8 最大能编码的 Unicode 字符是 0xffff,也就是 Unicode 中的基本多文种平面(BMP)。也就是说,任何不在基本多文本平面的 Unicode字符,都无法使用 Mysql 的 utf8 字符集存储。包括 Emoji 表情(Emoji 是一种特殊的 Unicode 编码,常见于 ios 和 android 手机上),和很多不常用的汉字,以及任何新增的 Unicode 字符等等。

总结:MySQL的utf8是utfmb3,只有三个字节,节省空间但不能表达全部的UTF-8。所以推荐使用utf8mb4。

utf8mb4_bin:将字符串每个字符用二进制数据编译存储,区分大小写,而且可以存二进制的内容。

utf8mb4_general_ci:ci即case insensitive,不区分大小写。没有实现Unicode排序规则,在遇到某些特殊语言或者字符集,排序结果可能不一致。但是,在绝大多数情况下,这些特殊字符的顺序并不需要那么精确。

utf8mb4_unicode_ci:是基于标准的Unicode来排序和比较,能够在各种语言之间精确排序,Unicode排序规则为了能够处理特殊字符的情况,实现了略微复杂的排序算法。

utf8mb4_general_ci是一个遗留的 校对规则,不支持扩展,它仅能够在字符之间进行逐个比较。utf8_general_ci校对规则进行的比较速度很快,但是与使用 utf8mb4_unicode_ci的校对规则相比,比较正确性较差。

总结:general_ci 更快,unicode_ci 更准确。但相比现在的CPU来说,它远远不足以成为考虑性能的因素,索引涉及、SQL设计才是。使用者更应该关心字符集与排序规则在db里需要统一。

版权声明:本文为CSDN博主「yzh_1346983557」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yzh_1346983557/article/details/89643071

===================================================================

.

发表在 db | mysql中的utf8mb4、utf8mb4_unicode_ci、utf8mb4_general_ci已关闭评论

C++ / C# 数据类型对照

C++ 输入输出    C# 
==================================
char chr[255]   O    StringBuilder
KCA_DIR            I    int
LPCSTR             I    string
int                        I    int
LPSTR              O    StringBuilder
int*                      O    out int
DWORD              I    int
DWORD*          O    out int
BOOL                 I    bool
Rc_DBMgr          I    IntPtr
long*                  O    out long
API与C#的数据类型对应关系表
API数据类型类型描述C#类型API数据类型类型描述C#类型
WORD16位无符号整数ushortCHAR字符char
LONG32位无符号整数intDWORDLONG64位长整数long
DWORD32位无符号整数uintHDC设备描述表句柄int
HANDLE句柄,32位整数intHGDIOBJGDI对象句柄int
UINT32位无符号整数uintHINSTANCE实例句柄int
BOOL32位布尔型整数boolHWM窗口句柄int
LPSTR指向字符的32位指针stringHPARAM32位消息参数int
LPCSTR指向常字符的32位指针StringLPARAM32位消息参数int
BYTE字节byteWPARAM32位消息参数int
Wtypes.h 中的非托管类型 非托管 C 语言类型 托管类名 说明
HANDLE void* System.IntPtr 32 位
BYTE unsigned char System.Byte 8 位
SHORT short System.Int16 16 位
WORD unsigned short System.UInt16 16 位
INT int System.Int32 32 位
UINT unsigned int System.UInt32 32 位
LONG long System.Int32 32 位
BOOL long System.Int32 32 位
DWORD unsigned long System.UInt32 32 位
ULONG unsigned long System.UInt32 32 位
CHAR char System.Char 用 ANSI 修饰。
LPSTR char* System.String 或System.StringBuilder 用 ANSI 修饰。
LPCSTR Const char* System.String 或System.StringBuilder 用 ANSI 修饰。
LPWSTR wchar_t* System.String 或System.StringBuilder 用 Unicode 修饰。
LPCWSTR Const wchar_t* System.String 或System.StringBuilder 用 Unicode 修饰。
FLOAT Float System.Single 32 位
DOUBLE Double System.Double 64 位

STDINT.H

typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
typedef signed __INT64 int64_t;

/* exact-width unsigned integer types */
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned __INT64 uint64_t;

/* 7.18.1.2 / / smallest type of at least n bits
/ / minimum-width signed integer types */
typedef signed char int_least8_t;
typedef signed short int int_least16_t;
typedef signed int int_least32_t;
typedef signed __INT64 int_least64_t;

/* minimum-width unsigned integer types */
typedef unsigned char uint_least8_t;
typedef unsigned short int uint_least16_t;
typedef unsigned int uint_least32_t;
typedef unsigned __INT64 uint_least64_t;

/* 7.18.1.3 / / fastest minimum-width signed integer types */
typedef signed int int_fast8_t;
typedef signed int int_fast16_t;
typedef signed int int_fast32_t;
typedef signed __INT64 int_fast64_t;

/* fastest minimum-width unsigned integer types */
typedef unsigned int uint_fast8_t;
typedef unsigned int uint_fast16_t;
typedef unsigned int uint_fast32_t;
typedef unsigned __INT64 uint_fast64_t;

typedef signed __INT64 intptr_t;
typedef unsigned __INT64 uintptr_t;

.

发表在 C# Code, c/c++ | C++ / C# 数据类型对照已关闭评论

C# 调用C++DLL传递指向指针的指针参数的方法

C++结构体定义:

struct DeviceInfo
{    
    char szDeviceName[DEVICE_NAME_LEN];
    char szMACAddress[MAC_ADDRESS_LEN];        
    char szDeviceIP[DEVICE_IP_LEN];
};

C#结构体的定义:

[StructLayout(LayoutKind.Sequential)]
public struct DeviceInfo
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
    public string szDeviceName;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 13)]
    public string szMACAddress;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
    public string szDeviceIP; 


}

情况1:C++的dll负责分配内存

C++导出函数的声明

#define DLL_API  extern "C"  __declspec(dllexport)
DLL_API int findAllDevices(DeviceInfo** ppDeviceInfoList,int * pCount);

C#导入函数的声明

[DllImport("IPAlter_d.dll")]
public extern static int findAllDevices(out IntPtr pDeviceInfo, ref int pCount);

C#的调用方法:

IntPtr pBuff = new IntPtr();//直接new一个参数即可
 if (IPAlter.findAllDevices(out pBuff, ref cout) != 1)
 {
     System.Console.WriteLine("搜索失败!");
     System.Console.ReadLine();
     return;
 }
 for (int i = 0; i < cout; i++)
 {
IntPtr pPonitor = new IntPtr(pBuff.ToInt64() + Marshal.SizeOf(typeof(DeviceInfo)) * i);

System.Console.WriteLine(((DeviceInfo)Marshal.PtrToStructure(pPonitor, typeof(DeviceInfo))).szDeviceName); 
 System.Console.WriteLine(((DeviceInfo)Marshal.PtrToStructure(pPonitor, typeof(DeviceInfo))).szDeviceIP); 
 System.Console.WriteLine(((DeviceInfo)Marshal.PtrToStructure(pPonitor, typeof(DeviceInfo))).szMACAddress);
 
 }

情况2:C#负责分配内存

C++导出函数的声明:

DLL_API int findAllDevice(DeviceInfo* ppDeviceInfoList,int * pCount);

 C#导入函数的声明:

[DllImport("IPAlter_d.dll")]
public extern static int findAllDevice(IntPtr pDeviceInfo, ref int pCount);

 C#的调用方法:

DeviceInfo[] DeviceInfoList = new DeviceInfo[50];
 int size = Marshal.SizeOf(typeof(DeviceInfo)) * 50;
 byte[] bytes = new byte[size];
 IntPtr pBuff = Marshal.AllocHGlobal(size);
 if (IPAlter.findAllDevice(pBuff, ref cout) != 1)
 {
     System.Console.WriteLine("搜索失败!");
     System.Console.ReadLine();
     return;
 }
 for (int i = 0; i < cout; i++)
 {

IntPtr pPonitor = new IntPtr(pBuff.ToInt64() + Marshal.SizeOf(typeof(DeviceInfo)) * i);
 DeviceInfoList[i] = (DeviceInfo)Marshal.PtrToStructure(pPonitor, typeof(DeviceInfo));
 System.Console.WriteLine(DeviceInfoList[i].szDeviceName);
 System.Console.WriteLine(DeviceInfoList[i].szDeviceIP);
 System.Console.WriteLine(DeviceInfoList[i].szMACAddress);


 }
 Marshal.FreeHGlobal(pBuff);

可以参考:

http://www.cnblogs.com/cxwx/archive/2010/12/29/1921140.html

http://hi.baidu.com/fanr520/item/e761f9ca0766d462f6c95d55

http://blog.csdn.net/wangweitingaabbcc/article/details/7663949

发表在 C# Code | C# 调用C++DLL传递指向指针的指针参数的方法已关闭评论

C#调用C/C++ DLL方式

1、编写一个简单的DLL

设置为导出函数,并采用C风格。函数前加extern "C" __declspec(dllexport)。定义函数在退出前自己清空堆栈,在函数前加__stdcall。

新建一个头文件,在头文件中:

/* 加入任意你想加入的函数定义*/

extern "C" _declspec(dllexport) int _stdcall add(int *x,int *y); // 声明为C编译、链接方式的外部函数
extern "C" _declspec(dllexport) int _stdcall sub(int x,int y); // 声明为C编译、链接方式的外部函数

新建一个.cpp文件

#include "mydll.h"//貌似这两个头文件的顺序不能颠倒。我试了很多次,但是不能确定。

int add(int *x,int *y)//是否可以理解为,VS2010已经默认是 _stdcall,所以函数不用添加该修饰符
{
return *x+*y;
}

int sub(int x,int y)
{
return x-y;
}

把导出函数名称变为标准名称,需加模块定义文件,就是.def文件。

内容如下:(需要注释,前面加分号就可以了,注释需要单独行)

LIBRARY "TEST"

     EXPORTS

          ;add函数

          add

   ;sub函数

         sub

LIBRARY 库名称

EXPORTS 需要导出的各个函数名称

     重新编译之后,再用Depends工具看一下,函数已经变成标准add。这个在动态加载时很有用,特别是在GetProcAddress函数寻找入库函数的时候。

2、静态调用

新建一个C#的控制台项目,

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;//添加

namespace mytest
{
  class Program
  {
    //----------------------------------------------------------------------------------------------
    [DllImport("mydll.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
    extern static int add(ref int a, ref int b);

    [DllImport("mydll.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
    extern static int sub(int a, int b);
    //--------------------------------------------------------------------------------------------------

    static void Main(string[] args)
    {

      int a, b,c,d;
      a = 1;
      b = 2;
      c=d= 0;

      Console.WriteLine(add(ref a,ref b).ToString());
      Console.WriteLine(sub(b,a).ToString());
      Console.Read();
    }
  }
}

 3、动态调用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;//添加

namespace mytest
{
  class Program
  {

[DllImport("kernel32.dll")]
private extern static IntPtr LoadLibrary(String path);//path 就是dll路径 返回结果为0表示失败。
[DllImport("kernel32.dll")]
private extern static IntPtr GetProcAddress(IntPtr lib, String funcName);//lib是LoadLibrary返回的句柄,funcName 是函数名称 返回结果为0标识失败。
[DllImport("kernel32.dll")]
private extern static bool FreeLibrary(IntPtr lib);

//声明委托
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
delegate int ADD(ref int x, ref int y);
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
delegate int SUB(int x, int y);

static void Main(string[] args)
{

string dllPath = "G:\\VS2010软件学习\\c#调用C_dll\\mytest\\mytest\\mydll.dll";
string apiName1 = "add";
string apiName2 = "sub";
//使用动态加载

IntPtr hLib = LoadLibrary(dllPath);//加载函数

IntPtr apiFunction1 = GetProcAddress(hLib, apiName1);//获取函数地址
IntPtr apiFunction2 = GetProcAddress(hLib, apiName2);//获取函数地址

int i = Marshal.GetLastWin32Error();
if (apiFunction1.ToInt32() == 0)//0表示函数没找到
return;
if (apiFunction2.ToInt32() == 0)//0表示函数没找到
return;

//获取函数接口,相当于函数指针
ADD add1 = (Delegate)Marshal.GetDelegateForFunctionPointer(apiFunction1, typeof(ADD)) as ADD;
SUB sub1 = (SUB)Marshal.GetDelegateForFunctionPointer(apiFunction2, typeof(SUB));

// //调用函数
int a, b,c;
a = 1;
b = 2;
c= 0;
//add1(ref a,ref b);
c=sub1(b,a);
// //释放句柄

FreeLibrary(hLib );

Console.WriteLine(c.ToString());
//Console.WriteLine(add(ref a,ref b).ToString());
//Console.WriteLine(sub(10,2).ToString());
Console.Read();

}

  }
}

注意:

C#时常需要调用C/C++DLL,当传递参数时时常遇到问题,尤其是传递和返回字符串时。VC++中主要字符串类型为:LPSTR,LPCSTR, LPCTSTR, string, CString, LPCWSTR, LPWSTR等,但转为C#类型却不完全相同。

类型对照:

C/C++----------C#

BSTR ---------  StringBuilder

LPCTSTR --------- StringBuilder

LPCWSTR ---------  IntPtr

handle---------IntPtr

hwnd-----------IntPtr

char *----------string

int * -----------ref int

int &-----------ref int

void *----------IntPtr

unsigned char *-----ref byte

Struct需要在C#里重新定义一个Struct

CallBack回调函数需要封装在一个委托里,delegate static extern int FunCallBack(string str);

注意在每个函数的前面加上public static extern +返回的数据类型,如果不加public ,函数默认为私有函数,调用就会出错。

在C#调用C++ DLL封装库时会出现两个问题:

1. 数据类型转换问题 
2. 指针或地址参数传送问题

发表在 C# Code | C#调用C/C++ DLL方式已关闭评论

Application Path

// 获取程序的基目录。
System.AppDomain.CurrentDomain.BaseDirectory

// 获取模块的完整路径。
System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName

// 获取和设置当前目录(该进程从中启动的目录)的完全限定目录。
System.Environment.CurrentDirectory

// 获取应用程序的当前工作目录。
System.IO.Directory.GetCurrentDirectory()

// 获取和设置包括该应用程序的目录的名称。
System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase

// 获取启动了应用程序的可执行文件的路径。
System.Windows.Forms.Application.StartupPath

// 获取启动了应用程序的可执行文件的路径及文件名
System.Windows.Forms.Application.ExecutablePath

AppDomain.CurrentDomain.BaseDirectory 返回结果为: D:\mycode\
Application.StartupPath 返回结果为: D:\mycode

.

.

发表在 C# Code | Application Path已关闭评论

串口、COM口、TTL、RS232、RS485

1、串口、COM口是指的物理接口形式(硬件)。而TTL、RS-232、RS-485是指的电平标准(电信号)。

2、接设备的时候,一般只接GND RX TX。不会接Vcc或者+3.3v的电源线,避免与目标设备上的供电冲突。

3、PL2303、CP2102芯片都是常用的USB转TTL串口的芯片,用USB来扩展串口(TTL电平)。

4、MAX232芯片是TTL电平与RS232电平的专用双向转换芯片,可以TTL转RS-232,也可以RS-232转TTL。

5、TTL标准是低电平为0,高电平为1(+5V电平)。RS-232标准是正电平为0,负电平为1(±15V电平)。

6、RS-485的电气特性:逻辑“1”以两线间的电压差为+(2—6)V表示;逻辑“0”以两线间的电压差为-(2—6)V表示。接口信号电平比RS-232-C降低了,就不易损坏接口电路的芯片,且该电平与TTL电平兼容,可方便与TTL电路连接。

    串口、COM口

    COM口即串行通讯端口,简称串口。一般我们见到的是两种物理标准。D型9针插头,和 4针杜邦头两种。下图是个USB转TTL串口的小板,可以用USB扩展出一个串口。对于使用笔记本或者没有COM的台机开发的嵌入式工程师来说就是必备工具。除了可以使用串口给MCU下载程序外,还是辅助调试程序的神器。

    RS232

上边介绍的都是USB转TTL串口,如果目标设备上是RS-232串口(D型9针接口)可咋整呀?再接一片MAX232转换一下就行,如下图。

    RS485

    在要求通信距离为几十米到上千米时,广泛采用RS-485串行总线标准。RS-485采用平衡发送和差分接收,因此具有抑制共模干扰的能力。RS-485接口的最大传输距离标准值为4000英尺(约1219米),实际上可达3000米,另外RS-232-C接口在总线上只允许连接1个收发器,即单站能力。而RS-485接口在总线上是允许连接多达128个收发器。

.

发表在 hardware | 串口、COM口、TTL、RS232、RS485已关闭评论

centos 7

timedatectl

timedatectl list-timezones | grep Asia
timedatectl set-timezone Asia/Shanghai

timedatectl list-timezones | grep UTC
timedatectl set-timezone UTC

; NTP
timedatectl set-ntp true
; timedatectl set-local-rtc true

systemctl status chrony
vi /etc/chrony.conf

hostname
hostnamectl --static set-hostname host-331582

vi /etc/selinux/config
echo 'SELINUX=disabled' >> /etc/selinux/config
echo '' >> /etc/selinux/config

.

发表在 linux | centos 7已关闭评论

Linux dd

一、dd命令的解释

dd:用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换。

注意:指定数字的地方若以下列字符结尾,则乘以相应的数字:b=512;c=1;k=1024;w=2

参数注释:

1. if=文件名:输入文件名,缺省为标准输入。即指定源文件。< if=input file >

2. of=文件名:输出文件名,缺省为标准输出。即指定目的文件。< of=output file >

3. ibs=bytes:一次读入bytes个字节,即指定一个块大小为bytes个字节。

    obs=bytes:一次输出bytes个字节,即指定一个块大小为bytes个字节。

    bs=bytes:同时设置读入/输出的块大小为bytes个字节。

4. cbs=bytes:一次转换bytes个字节,即指定转换缓冲区大小。

5. skip=blocks:从输入文件开头跳过blocks个块后再开始复制。

6. seek=blocks:从输出文件开头跳过blocks个块后再开始复制。

注意:通常只用当输出文件是磁盘或磁带时才有效,即备份到磁盘或磁带时才有效。

7. count=blocks:仅拷贝blocks个块,块大小等于ibs指定的字节数。

8. conv=conversion:用指定的参数转换文件。

    ascii:转换ebcdic为ascii

     ebcdic:转换ascii为ebcdic

    ibm:转换ascii为alternate ebcdic

    block:把每一行转换为长度为cbs,不足部分用空格填充

    unblock:使每一行的长度都为cbs,不足部分用空格填充

    lcase:把大写字符转换为小写字符

    ucase:把小写字符转换为大写字符

    swab:交换输入的每对字节

     noerror:出错时不停止

     notrunc:不截短输出文件

    sync:将每个输入块填充到ibs个字节,不足部分用空(NUL)字符补齐。

二、dd应用实例

1.将本地的/dev/hdb整盘备份到/dev/hdd

#dd if=/dev/hdb of=/dev/hdd

2./dev/hdb全盘数据备份到指定路径的image文件

#dd if=/dev/hdb of=/root/image

3.将备份文件恢复到指定盘

#dd if=/root/image of=/dev/hdb

4.备份/dev/hdb全盘数据,并利用gzip工具进行压缩,保存到指定路径

#dd if=/dev/hdb | gzip > /root/image.gz

5.将压缩的备份文件恢复到指定盘

#gzip -dc /root/image.gz | dd of=/dev/hdb

6.备份与恢复MBR

备份磁盘开始的512个字节大小的MBR信息到指定文件:

#dd if=/dev/hda of=/root/image count=1 bs=512

   count=1指仅拷贝一个块;bs=512指块大小为512个字节。

恢复:

#dd if=/root/image of=/dev/had

将备份的MBR信息写到磁盘开始部分

7.备份软盘

#dd if=/dev/fd0 of=disk.img count=1 bs=1440k (即块大小为1.44M)

8.拷贝内存内容到硬盘

#dd if=/dev/mem of=/root/mem.bin bs=1024 (指定块大小为1k)  

9.拷贝光盘内容到指定文件夹,并保存为cd.iso文件

#dd if=/dev/cdrom(hdc) of=/root/cd.iso

10.增加swap分区文件大小

第一步:创建一个大小为256M的文件:

#dd if=/dev/zero of=/swapfile bs=1024 count=262144

第二步:把这个文件变成swap文件:

#mkswap /swapfile

第三步:启用这个swap文件:

#swapon /swapfile

第四步:编辑/etc/fstab文件,使在每次开机时自动加载swap文件:

/swapfile    swap    swap    default   0 0

11.销毁磁盘数据

#dd if=/dev/urandom of=/dev/hda1

注意:利用随机的数据填充硬盘,在某些必要的场合可以用来销毁数据。

12.测试硬盘的读写速度

#dd if=/dev/zero bs=1024 count=1000000 of=/root/1Gb.file

#dd if=/root/1Gb.file bs=64k | dd of=/dev/null

通过以上两个命令输出的命令执行时间,可以计算出硬盘的读、写速度。

13.确定硬盘的最佳块大小:

#dd if=/dev/zero bs=1024 count=1000000 of=/root/1Gb.file

#dd if=/dev/zero bs=2048 count=500000 of=/root/1Gb.file

#dd if=/dev/zero bs=4096 count=250000 of=/root/1Gb.file

#dd if=/dev/zero bs=8192 count=125000 of=/root/1Gb.file

通过比较以上命令输出中所显示的命令执行时间,即可确定系统最佳的块大小。

14.修复硬盘:

#dd if=/dev/sda of=/dev/sda 或dd if=/dev/hda of=/dev/hda

当硬盘较长时间(一年以上)放置不使用后,磁盘上会产生magnetic flux point,当磁头读到这些区域时会遇到困难,并可能导致I/O错误。当这种情况影响到硬盘的第一个扇区时,可能导致硬盘报废。上边的命令有可能使这些数 据起死回生。并且这个过程是安全、高效的。

15.利用netcat远程备份

#dd if=/dev/hda bs=16065b | netcat < targethost-IP > 1234

在源主机上执行此命令备份/dev/hda

#netcat -l -p 1234 | dd of=/dev/hdc bs=16065b

在目的主机上执行此命令来接收数据并写入/dev/hdc

#netcat -l -p 1234 | bzip2 > partition.img

#netcat -l -p 1234 | gzip > partition.img

以上两条指令是目的主机指令的变化分别采用bzip2、gzip对数据进行压缩,并将备份文件保存在当前目录。

16.将一个大视频文件的第i个字节的值改成0x41(大写字母AASCII值)

#echo A | dd of=bigfile seek=$i bs=1 count=1 conv=notrunc

17.建立linux虚拟盘,用文件模拟磁盘

在进行linux的实验中,如果没有多余的硬盘来做测试。则可以在linux下使用文件来模拟磁盘,以供测试目的。

其模拟过程如下所示,摘录自《Oracle数据库核心技术与实务详解-教你如何成为Oracle 10g OCP》一书。

1)以root用户创建一个ASM磁盘所在的目录。

# mkdir –p /u01/asmdisks

2)通过dd命令创建6个400M大小的文件,每个文件代表一块磁盘。

[root@book u01]

# cd asmdisks

[root@book asmdisks]

# dd if=/dev/zero of=asm_disk1 bs=1024k count=400

[root@book asmdisks]

# dd if=/dev/zero of=asm_disk2 bs=1024k count=400

[root@book asmdisks]

# dd if=/dev/zero of=asm_disk3 bs=1024k count=400

[root@book asmdisks]

# dd if=/dev/zero of=asm_disk4 bs=1024k count=400

[root@book asmdisks]

# dd if=/dev/zero of=asm_disk5 bs=1024k count=400

[root@book asmdisks]

# dd if=/dev/zero of=asm_disk6 bs=1024k count=400

3)将这些文件与裸设备关联。

[root@book asmdisks]

# chmod 777 asm_disk*

[root@book asmdisks]

# losetup /dev/loop1 asm_disk1

[root@book asmdisks]

# losetup /dev/loop2 asm_disk2

[root@book asmdisks]

# losetup /dev/loop3 asm_disk3

[root@book asmdisks]

# losetup /dev/loop4 asm_disk4

[root@book asmdisks]

# losetup /dev/loop5 asm_disk5

[root@book asmdisks]

# losetup /dev/loop6 asm_disk6

注意:如果要删除通过dd模拟出的虚拟磁盘文件的话,直接删除模拟出的磁盘文件

(也就是asm_disk1、asm_disk2…asm_disk6)还不够,还必须执行losetup -d /dev/loopN,在这里N从1到6。否则,磁盘文件所占用的磁盘空间不能释放

三、/dev/null和/dev/zero的区别

/dev/null,外号叫无底洞,你可以向它输出任何数据,它通吃,并且不会撑着!

/dev/zero,是一个输入设备,你可你用它来初始化文件。该设备无穷尽地提供0,可以使用任何你需要的数目——设备提供的要多的多。他可以用于向设备或文件写入字符串0。

/dev/null------它是空设备,也称为位桶(bit bucket)。任何写入它的输出都会被抛弃。如果不想让消息以标准输出显示或写入文件,那么可以将消息重定向到位桶。

#if=/dev/zero of=./test.txt bs=1k count=1
#ls –l

total 4
-rw-r--r--    1 oracle   dba          1024 Jul 15 16:56 test.txt

#find / -name access_log  2>/dev/null

3.1使用/dev/null 

把/dev/null看作"黑洞", 它等价于一个只写文件,所有写入它的内容都会永远丢失.,而尝试从它那儿读取内容则什么也读不到。然而, /dev/null对命令行和脚本都非常的有用

禁止标准输出

#cat $filename >/dev/null

文件内容丢失,而不会输出到标准输出.

禁止标准错误

#rm $badname 2>/dev/null

这样错误信息[标准错误]就被丢到太平洋去了

禁止标准输出和标准错误的输出

#cat $filename 2>/dev/null >/dev/null

如果"filename"不存在,将不会有任何错误信息提示;如果"

filename"存在, 文件的内容不会打印到标准输出。

因此,上面的代码根本不会输出任何信息。当只想测试命令的退出码而不想有任何输出时非常有用。

#cat $filename &>/dev/null

这样其实也可以, 由 Baris Cicek 指出

自动清空日志文件的内容

Deleting contents of a file, but preserving the file itself, with all attendant permissions (from Example 2-1 and Example 2-3): 

#cat /dev/null > /var/log/messages
#  : > /var/log/messages   有同样的效果, 但不会产生新的进程.(因为:是内建的)
#cat /dev/null > /var/log/wtmp

特别适合处理这些由商业Web站点发送的讨厌的"cookies"

隐藏cookie而不再使用

#if [ -f ~/.netscape/cookies ]  # 如果存在则删除.
#then
#rm -f ~/.netscape/cookies
#fi
#ln -s /dev/null ~/.netscape/cookies

现在所有的cookies都会丢入黑洞而不会保存在磁盘上了.

3.2使用/dev/zero

像/dev/null一样, /dev/zero也是一个伪文件, 但它实际上产生连续不断的null的流(二进制的零流,而不是ASCII型的)。 写入它的输出会丢失不见, 而从/dev/zero读出一连串的null也比较困难, 虽然这也能通过od或一个十六进制编辑器来做到。 /dev/zero主要的用处是用来创建一个指定长度用于初始化的空文件,就像临时交换文件

/dev/zero创建一个交换临时文件

#!/bin/bash

  # 创建一个交换文件.

  ROOT_UID=0 # Root 用户的 $UID 是 0.

  E_WRONG_USER=65 # 不是 root?

  FILE=/swap

  BLOCKSIZE=1024

  MINBLOCKS=40

  SUCCESS=0

  # 这个脚本必须用root来运行.

  if [ "UID"−ne"

ROOT_UID" ]

   then

   echo; echo "You must be root to run this script."; echo

   exit $E_WRONG_USER

  fi

  blocks={1:-

MINBLOCKS} # 如果命令行没有指定,

  #+ 则设置为默认的40块.

  # 上面这句等同如:

  # --------------------------------------------------

  # if [ -n "$1" ]

  # then

  # blocks=$1

  # else

  # blocks=$MINBLOCKS

  # fi

  # --------------------------------------------------

 if [ "blocks"−lt

MINBLOCKS ]

 then

 blocks=$MINBLOCKS # 最少要有 40 个块长.

 fi

 echo "Creating swap file of size $blocks blocks (KB)."

 dd if=/dev/zero of=FILEbs=

BLOCKSIZE count=$blocks # 把零写入文件.

 mkswap FILE

blocks # 将此文件建为交换文件(或称交换分区).

 swapon $FILE # 激活交换文件.

 echo "Swap file created and activated."

 exit $SUCCESS 

关于 /dev/zero 的另一个应用是为特定的目的而用零去填充一个指定大小的文件, 如挂载一个文件系统到环回设备 (loopback device)或"安全地" 删除一个文件

例子创建ramdisk

#!/bin/bash

 # ramdisk.sh

 # "ramdisk"是系统RAM内存的一段,

 #+ 它可以被当成是一个文件系统来操作.

 # 它的优点是存取速度非常快 (包括读和写).

 # 缺点: 易失性, 当计算机重启或关机时会丢失数据.

 #+ 会减少系统可用的RAM.

 # 10 # 那么ramdisk有什么作用呢?

 # 保存一个较大的数据集在ramdisk, 比如一张表或字典,

 #+ 这样可以加速数据查询, 因为在内存里查找比在磁盘里查找快得多.

  E_NON_ROOT_USER=70 # 必须用root来运行.

  ROOTUSER_NAME=root

  MOUNTPT=/mnt/ramdisk

  SIZE=2000 # 2K 个块 (可以合适的做修改)

  BLOCKSIZE=1024 # 每块有1K (1024 byte) 的大小

  DEVICE=/dev/ram0 # 第一个 ram 设备

  username=`id -nu`

  if [ "username"!="

ROOTUSER_NAME" ]

  then

    echo "Must be root to run \"`basename $0`\"."

    exit $E_NON_ROOT_USER

  fi

   if [ ! -d "$MOUNTPT" ] # 测试挂载点是否已经存在了,

  then #+ 如果这个脚本已经运行了好几次了就不会再建这个目录了

    mkdir $MOUNTPT #+ 因为前面已经建立了.

  fi

  dd if=/dev/zero of=DEVICEcount=

SIZE bs=$BLOCKSIZE

   # 把RAM设备的内容用零填充.                                              

   # 为何需要这么做?

  mke2fs $DEVICE # 在RAM设备上创建一个ext2文件系统.

  mount DEVICE

MOUNTPT # 挂载设备.

  chmod 777 $MOUNTPT # 使普通用户也可以存取这个ramdisk.

  # 但是, 只能由root来缷载它.

  echo "\"$MOUNTPT\" now available for use."

 # 现在 ramdisk 即使普通用户也可以用来存取文件了.

 # 注意, ramdisk是易失的, 所以当计算机系统重启或关机时ramdisk里的内容会消失.

 # 拷贝所有你想保存文件到一个常规的磁盘目录下.

 # 重启之后, 运行这个脚本再次建立起一个 ramdisk.

 # 仅重新加载 /mnt/ramdisk 而没有其他的步骤将不会正确工作.

 # 如果加以改进, 这个脚本可以放在 /etc/rc.d/rc.local,

 #+ 以使系统启动时能自动设立一个ramdisk.

 # 这样很合适速度要求高的数据库服务器.

 exit 0

Links:

https://www.cnblogs.com/jikexianfeng/p/6103500.html

发表在 linux | Linux dd已关闭评论