2017年11月

Read 23 byte data:HelloWorld
HelloMaQian


## 四、关于lseek

lseek用于设置文件指针的位置,同时也可以查看当前指针所处的位置。

如果设置的文件指针超过了文件范围,系统将会给文件申请更多的内存空间来存储这些超出的文件数据,但这要求系统要在指针所指向的位置进行一次写操作。

include "apue.h"

include <fcntl.h>

int main() {

int fd, ret;

const char *s1 = "abcdefghij";
const char *s2 = "ABCDEFGHIJ";

fd = open("test.hole", O_WRONLY | O_CREAT | O_TRUNC, 0755);
if (-1 == fd)
    err_sys("open file error");

if (write(fd, s1, 10) != 10)
    err_sys("write s1 error");
if ((ret = lseek(fd, 0, SEEK_CUR)) < 0)
    err_sys("lseek error");
printf("localtion: %d\n", ret); // 打印当前的指针位置 10

if ((ret = lseek(fd, 1000, SEEK_SET)) < 0)
    err_sys("lseek error");
printf("localtion: %d\n", ret); // 移动后的位置 1000

if (write(fd, s2, 10) != 10)
    err_sys("write s2 error");
close(fd);
return 0;

}


运行程序后输出:
./a.out
localtion: 10
localtion: 1000
ll test.hole
-rwxr-xr-x 1 ma ma 1010 May 18 11:18 test.hole # 文件大小1010字节

### 4.1 使用lseek生成指定大小的文件

根据上面所描述的`lseek`的特性,文件指针超出时会自动申请空间,因此我们可以通过它来生成一个指定大小的文件。

include "apue.h"

include <fcntl.h>

const int BT_SIZE = 1;
const int KB_SIZE = 1 << 10;
const int MB_SIZE = 1 << 20;
const int GB_SIZE = 1 << 30;

/*

  • 解析输入的文件大小
  • @size 大小字符串1g, 1m, 1k, 1
  • @return 返回解析好的字节数
  • 失败直接退出程序
    */

int parser_size(const char *size)
{

int i = 0, n = 0;
char ch; // 遍历每一个字符
while ((ch = size[i]))
{
    if ((''a'' <= ch && ch <= ''z'') || (''A'' <= ch && ch <= ''Z''))
    {
        if(size[i + 1])
            err_quit("invalid input: %s", size);
        switch (ch)
        {
        case ''b'':
        case ''B'':
            return BT_SIZE * n;
        case ''k'':
        case ''K'':
            return KB_SIZE * n;
        case ''m'':
        case ''M'':
            return MB_SIZE * n;
        case ''g'':
        case ''G'':
            return GB_SIZE * n;
        default:
            err_quit("invalid input: %c", ch);
        }
    }
    else if (''0'' <= ch && ch <= ''9'')
    {
        n = 10 * n + ch - ''0'';
    }
    else
    {
        err_quit("invalid input: %s", size);
    }
    i++;
}
return n;

}

int main(int argc, char **argv)
{

if (argc < 3)
    err_quit("Usage: ./mkfile filename size");

int sz = parser_size(argv[2]);

int fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0755);
if (-1 == fd)
    err_sys("crate file error");

// 移动到指定位置的前一个字节
if (-1 == lseek(fd, sz - 1, SEEK_SET))
    err_sys("create file error");

// 写入一个字节申请内存块
if (1 != write(fd, " ", 1))
    err_sys("write data error");

close(fd);
return 0;

}


根据输入即可生成指定大小的文件:
mkdir debug && gcc main.c /apue.* -o debug/app
./debug/app test1 1g
./debug/app test2 2m
./debug/app test3 3k
./debug/app test4 4
ll
total 32K
drwxrwxr-x 2 ma ma 4.0K May 18 14:40 debug
-rw-rw-r-- 1 ma ma 1.7K May 18 14:39 main.c
-rw-rw-r-- 1 ma ma 1.7K May 18 14:35 main.c.orig
-rw-rw-r-- 1 ma ma 311 May 18 14:22 Makefile
-rwxr-xr-x 1 ma ma 1.0G May 18 14:41 test1
-rwxr-xr-x 1 ma ma 2.0M May 18 14:41 test2
-rwxr-xr-x 1 ma ma 3.0K May 18 14:41 test3
-rwxr-xr-x 1 ma ma 4 May 18 14:41 test4

不过对于文件的大小有个限制,文件最多只能`2G+`,因为此时计算出来的`sz`大小会溢出。

一、问题描述

给网站加了CDN 后,网页的部分字体加载不出,同时一些图标也会显示异常:

控制台报以下错误:

Access to Font at "http://test.dyxmq.cn/wp-content/themes/chuxia3.0/fonts/iconfont.ttf" from origin "http://www.dyxmq.cn" has been blocked by CORS policy: No "Access-Control-Allow-Origin" header is present on the requested resource. Origin "http://www.dyxmq.cn" is therefore not allowed access. The response had HTTP status code 404

- 阅读剩余部分 -

一、基本用法

任何一门程序语言都离不开位运算这个功能,redis虽然不是一门编程语言,但也是一个和编程密切关联的工具。因此位运算自然也是redis中不可或缺的功能。

redis中位运算相关的方法:

  • GETBIT key offset: 获取第offset位的bit,不存的的比特位返回0。
  • SETBIT key offset value: 给第offset位设置成value。
  • BITCOUNT key [start] [end]: 计算key中1的个数。
  • BITOP operation destkey key [key]: 执行位操作,位操作包含与(AND)或(OR)异或(XOR)以及 非(NOT)
  • BITPOS key value [start] [end]: 查询key中第一次出现value的位置,startend表示字符的开始和结束位置。

- 阅读剩余部分 -

一、基本用法

字符串是redis中的基本数据类型之一,能存储任何形式的字符串,包括二进制数据。同时,它还可以进行字符串运算数据运算位运算等操作。一个字符串最大能有512M。

字符串主要的操作命令有两个:

  • GET KEY: 如果KEY存在就返回对应的值,如果不存在则返回空值nil
  • SET KEY VALUE: 给KEY设置值为VALUE,如果KEY已经存在则更新值。

- 阅读剩余部分 -

+
1 row in set (0.00 sec)


当要更新数据的时候根据带上版本号更新:

mysql> update lock_test set name = "xiaoming", version = version + 1 where id = 1 and version = 0;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0


第二个终端再根据`0` 的版本号更新数据就不会操作成功:

mysql> update lock_test set name = "xxxxxx", version = version + 1 where id = 1 and version = 0;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0 Changed: 0 Warnings: 0 -- 影响行数为0

+
1 row in set (0.00 sec)


当查询没有明确指定主键字段值时,锁的范围是整张表。例如我们使用终端一通过`name="maqian"`  来查询的时候,整个表都会被锁住,其他事务查询任何内容都会失败:

mysql> select * from lock_test where name = "xiaoming" for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

MySQL事务的隔离级别

一、事务并发带来的问题

1.1 第一类丢失更新

两个事务同时更新一行数据,第一个事务正常更新,第二个事务中途退出回滚数据到初始状态,导致第一个事务更新失效。

如:银行卡存储了用户甲的余额4000,此时事务A和B同时开始更新余额,事务A将余额更新到5000后正常退出,事务B执行出错导致更新失败,然后回滚余额到开始的状态4000。于是就产生了第一类丢失更新。

- 阅读剩余部分 -

一、什么是事务

事务是一组SQL语句构成的语句集合,它保证所有的SQL都能全部执行或者全部不执行。

事务必须满足四个条件(ACID):Atomicity 原子性 Consistency 一致性 Isolation 隔离性`Durability 持久性`

  • 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
  • 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
  • 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
  • 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

工作流程为:

MySQL对事务的支持与引擎有关:

  • MyISAM:不支持事务,用于只读程序提高性能。
  • InnoDB:支持ACID事务、行级锁、并发。

二、使用方法

执行事务的方法很简单,只要在需要执行的SQL语句前后分别加上BEGINCOMMIT即可,即:

BEGIN;
SQL 1;
SQL 2;
...
COMMIT;
默认情况下,SQL语句都是默认提交的,即每次执行SQL语句后都会自动加上提交动作。使用set autocommit = 0命令可将语句设置成不自动提交。

三、示例

1.创建一张测试表

mysql> create table test(
    -> id int primary key auto_increment,
    -> name varchar(20) not null default "",
    -> age tinyint unsigned not null
    -> );
Query OK, 0 rows affected (0.22 sec)

在不使用事务的情况下插入一行数据:

mysql> insert into test values(1, "maqian", 21);
Query OK, 1 row affected (0.07 sec)
mysql> select * from test;
+----+--------+-----+
| id | name   | age |
+----+--------+-----+
|  1 | maqian |  21 |
+----+--------+-----+
1 row in set (0.00 sec)

2.使用事务插入一行数据

-- 开始事务
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
-- 插入数据
mysql> insert into test values(2, "xiaoming", 20);
Query OK, 1 row affected (0.00 sec)
-- 查看当前数据
mysql> select * from test;
+----+----------+-----+
| id | name     | age |
+----+----------+-----+
|  1 | maqian   |  21 |
|  2 | xiaoming |  20 |
+----+----------+-----+
2 rows in set (0.00 sec)
-- 提交
mysql> commit;
Query OK, 0 rows affected (0.03 sec)
-- 数据仍然存在
mysql> select * from test;  
+----+----------+-----+
| id | name     | age |
+----+----------+-----+
|  1 | maqian   |  21 |
|  2 | xiaoming |  20 |
+----+----------+-----+
2 rows in set (0.00 sec)

3.回滚事务

mysql> insert into test values(3, "xiaohua", 1);
Query OK, 1 row affected (0.00 sec)
-- 插入了一行数据
mysql> select * from test;
+----+----------+-----+
| id | name     | age |
+----+----------+-----+
|  1 | maqian   |  21 |
|  2 | xiaoming |  20 |
|  3 | xiaohua  |   1 |
+----+----------+-----+
3 rows in set (0.00 sec)
-- 回滚
mysql> rollback;
Query OK, 0 rows affected (0.02 sec)
-- 被插入的行被回滚了,数据库回到插入前的状态
mysql> select * from test;
+----+----------+-----+
| id | name     | age |
+----+----------+-----+
|  1 | maqian   |  21 |
|  2 | xiaoming |  20 |
+----+----------+-----+
2 rows in set (0.00 sec)

计算机网络体系结构有三种:OSI分层(7层)、五层协议(5层)和TCP/IP分层(4层)。

三者之间的分层示意图:

每一层的作用如下:

  • 物理层:通过媒介传输比特,确定机械及电气规范(比特Bit)
  • 数据链路层:将比特组装成帧和点到点的传递(帧Frame)
  • 网络层:负责数据包从源到宿的传递和网际互连(包PackeT)
  • 传输层:提供端到端的可靠报文传递和错误恢复(段Segment)
  • 会话层:建立、管理和终止会话(会话协议数据单元SPDU)
  • 表示层:对数据进行翻译、加密和压缩(表示协议数据单元PPDU)
  • 应用层:允许访问OSI环境的手段(应用协议数据单元APDU)

各层包含的协议:

  • 物理层:RJ45、CLOCK、IEEE802.3
  • 数据链路:PPP、FR、HDLC、VLAN、MAC
  • 网络层:IP、ICMP、ARP、RARP、OSPF、IPX、RIP、IGRP
  • 传输层:TCP、UDP、SPX
  • 会话层:NFS、SQL、NETBIOS、RPC
  • 表示层:JPEG、MPEG、ASII
  • 应用层:FTP、DNS、Telnet、SMTP、HTTP、WWW、NFS
在计算机网络中,我们通常使用的是5层表示法。因此数据链路层也被称为二层,网络层被称为三层。