磁盘分区
1 | fdisk -l |
1 | fdisk -l |
sql是什么
SQL (发音为字母 S-Q-L 或 sequel )是结构化查询语言( Structured Query Language )的缩写。 SQL 是一种专门用来与数据库沟通的语言。
为什么
设计 SQL 的目的是很好地完成一项任务 —— 提供一种从数据库中读写数据的简单有效的方法。
标准 SQL 由 ANSI 标准委员会管理,从而称为 ANSI SQL 。
注意:数据类型兼容
数据类型及其名称是 SQL 不兼容的一个主要原因。虽然大多数基本数据类型得到了一致的支持,但许多高级的数据类型却没有。更糟的是,
偶然会有相同的数据类型在不同的 DBMS 中具有不同的名称。
行(row)
表中的一个记录。表中的数据是按行存储的,所保存的每个记录存储在自己的行内。
主键( primary key )
一列(或一组列),其值能够唯一标识表中每一行。
主键的条件:
- 任意两行都不具有相同的主键值;
- 每一行都必须具有一个主键值(主键列不允许NULL值);
- 主键列中的值不允许修改或更新;
- 主键值不能重用(如果某行从表中删除,它的主键不能赋给以后的新行)。
提示:
结束 SQL 语句。多条 SQL 语句必须以分号(;)分隔。多数 DBMS 不需要在单条 SQL 语句后加分号。
SQL 语句不区分大小写,因此SELECT与select是相同的。
使用空格。在处理 SQL 语句时,其中所有空格都被忽略。
当心逗号。在选择多个列时,一定要在列名之间加上逗号,但最后一个列名后不加。如果在最后一个列名后加了逗号,将出现错误
注释:
单行:“#” 开头
多行:/* */
ORDER BY 子句的位置
在指定一条ORDER BY子句时,应该保证它是SELECT语句中最后一条子句。如果它不是最后的子句,将会出现错误消息
下面的代码检索 3 个列,并按其中两个列对结果进行排序 —— 首先按价格,然后按名称排序。
1 | SELECT prod_id, prod_price, prod_name |
1 | SELECT prod_id, prod_price, prod_name |
ORDER BY 2,3表示先按prod_price,再按prod_name进行排序。
DESC
DESC关键字只应用到直接位于其前面的列名。
警告:在多个列上降序排序
如果想在多个列上进行降序排序,必须对每一列指定DESC关键字。
在SELECT语句中,数据根据WHERE子句中指定的搜索条件进行过滤。WHERE子句在表名(FROM子句)之后给出,
警告: WHERE 子句的位置
在同时使用ORDER BY和WHERE子句时,应该让ORDER BY位于WHERE之后,否则将会产生错误
操作符 | 说 明 |
---|---|
BETWEEN | 在指定的两个值之间 |
IS NULL | 为 NULL 值 |
< > | 不等于 |
1 | SELECT prod_name, prod_price |
这条SELECT语句与前一条的唯一差别是,将前两个条件用圆括号括了起来。因为圆括号具有比AND或OR操作符更高的求值顺序,所以 DBMS 首先
过滤圆括号内的OR条件。这时, SQL 语句变成了选择由供应商DLL01或BRS01制造的且价格在 10 美元及以上的所有产品,这正是我们希望的结
果。
提示:在WHERE子句中使用圆括号
任何时候使用具有AND和OR操作符的WHERE子句,都应该使用圆括号明确地分组操作符。
为什么要使用IN操作符?其优点为:
在有很多合法选项时,IN操作符的语法更清楚,更直观。 在与其他AND和OR操作符组合使用IN时,求值顺序更容易管理。 IN操作符一般比一组OR操作符执行得更快(在上面这个合法选项很少的例子中,你看不出性能差异)。 IN的最大优点是可以包含其他SELECT语句,能够更动态地建立WHERE子句。
最常使用的通配符是百分号(%)。在搜索串中,%表示任何字符出现任意次数。
说明:区分大小写
根据DBMS的不同及其配置,搜索可以是区分大小写的。如果区分大小写,则’fish%’与Fish bean bag toy就不匹配。
警告:请注意NULL
通配符%看起来像是可以匹配任何东西,但有个例外,这就是NULL。子句WHERE prod_name LIKE ‘%’不会匹配产品名称为NULL的行。
另一个有用的通配符是下划线(_)。下划线的用途与%一样,但它只匹配单个字符,而不是多个字符。
说明:DB2通配符 DB2不支持通配符_。 _
_说明:Access通配符
如果使用的是Microsoft Access,需要使用?而不是_。
方括号 ([]) 通配符用来指定一个字符集,它必须匹配指定位置(通配符的位置)的一个字符。
不要过度使用通配符。如果其他操作符能达到相同的目的,应该使用其他操作符。
在确实需要使用通配符时,也尽量不要把它们用在搜索模式的开始处。把通配符置于开始处,搜索起来是最慢的。
仔细注意通配符的位置。如果放错地方,可能不会返回想要的数据。
CustomersCustomers
加减乘除(+ - * /)
DBMS 函数的差异
函 数 | 语 法 |
---|---|
提取字符串的组成部分 | Access 使用 MID() ; DB2 、 Oracle 、 PostgreSQL 和 SQLite 使用 SUBSTR() ; MySQL 和 SQL Server 使用 SUBSTRING() |
数据类型转换 | Access 和 Oracle 使用多个函数,每种类型的转换有一个函数; DB2 和 PostgreSQL 使用 CAST() ; MariaDB 、 MySQL 和 SQL Server 使用 CONVERT() |
取当前日期 | Access 使用 NOW() ; DB2 和 PostgreSQL 使用 CURRENT_DATE ; MariaDB 和 MySQL 使用 CURDATE() ; Oracle 使用 SYSDATE ; SQL Server 使用 GETDATE() ; SQLite 使用 DATE() |
函 数 | 说 明 |
---|---|
LEFT() (或使用子字符串函数) | 返回字符串左边的字符 |
LENGTH() (也使用 DATALENGTH() 或 LEN() ) | 返回字符串的长度 |
LOWER() ( Access 使用 LCASE() ) | 将字符串转换为小写 |
LTRIM() | 去掉字符串左边的空格 |
RIGHT() (或使用子字符串函数) | 返回字符串右边的字符 |
RTRIM() | 去掉字符串右边的空格 |
SOUNDEX() | 返回字符串的 SOUNDEX 值 |
UPPER() ( Access 使用 UCASE() ) | 将字符串转换为大写 |
函 数 | 说 明 |
---|---|
ABS() | 返回一个数的绝对值 |
COS() | 返回一个角度的余弦 |
EXP() | 返回一个数的指数值 |
PI() | 返回圆周率 |
SIN() | 返回一个角度的正弦 |
SQRT() | 返回一个数的平方根 |
TAN() | 返回一个角度的正切 |
SQL 聚集函数
函 数 | 说 明 |
---|---|
AVG() | 返回某列的平均值 |
COUNT() | 返回某列的行数 |
MAX() | 返回指定列的最大值 |
MIN() | 返回某列的最小值 |
SUM() | 返回某列值之和 |
警告:只用于单个列
AVG()只能用来确定特定数值列的平均值,而且列名必须作为函数参数给出。为了获得多个列的平均值,必须使用多个AVG()函数。
AVG()函数忽略列值为NULL的行。
使用COUNT(*)对表中行的数目进行计数,不管表列中包含的是空值(NULL)还是非空值。
使用COUNT(column)对特定列中具有值的行进行计数,忽略NULL值。
提示:对非数值数据使用MAX()
虽然MAX()一般用来找出最大的数值或日期值,但许多(并非所有)DBMS允许将它用来返回任意列中的最大值,包括返回文本列中的最大 值。在用于文本数据时,MAX()返回按该列排序后的最后一行。
说明:NULL值
MAX()函数忽略列值为NULL的行。
SUM()用来返回指定列值的和(总计)。
在使用GROUP BY子句前,需要知道一些重要的规定。
GROUP BY子句可以包含任意数目的列,因而可以对分组进行嵌套,更细致地进行数据分组。
如果在GROUP BY子句中嵌套了分组,数据将在最后指定的分组上进行汇总。换句话说,在建立分组时,指定的所有列都一起计算(所以不能从个别的列取回数据)。
GROUP BY子句中列出的每一列都必须是检索列或有效的表达式(但不能是聚集函数)。如果在SELECT中使用表达式,则必须在GROUP BY子句中指定相同的表达式。不能使用别名。
大多数SQL实现不允许GROUP BY列带有长度可变的数据类型(如文本或备注型字段)。
除聚集计算语句外,SELECT语句中的每一列都必须在GROUP BY子句中给出。
如果分组列中包含具有NULL值的行,则NULL将作为一个分组返回。如果列中有多行NULL值,它们将分为一组。
GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前。
HAVING和WHERE的差别
WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤。这是一个重要的区别,WHERE排除的行不包括在分组 中。这可能会改变计算值,从而影响HAVING子句中基于这些值过滤掉的分组。
使用HAVING时应该结合GROUP BY子句,而WHERE子句用于标准的行级过滤。
视图为虚拟的表。它们包含的不是数据而是根据需要检索数据的查询。视图提供了一种封装SELECT语句的层次,可用来简化数据处理,重新格 式化或保护基础数据。
视图是虚拟的表。与包含数据的表不一样,视图只包含使用时动态检索数据的查询。
重用SQL语句。
简化复杂的SQL操作。在编写查询后,可以方便地重用它而不必知道其基本查询细节。
使用表的一部分而不是整个表。
保护数据。可以授予用户访问表的特定部分的权限,而不是整个表的访问权限。
更改数据格式和表示。视图可返回与底层表的表示和格式不同的数据。
警告:性能问题
因为视图不包含数据,所以每次使用视图时,都必须处理查询执行时需要的所有检索。如果你用多个联结和过滤创建了复杂的视图或者嵌套 了视图,性能可能会下降得很厉害。因此,在部署使用了大量视图的应用前,应该进行测试。
与表一样,视图必须唯一命名(不能给视图取与别的视图或表相同的名字)。
对于可以创建的视图数目没有限制。
创建视图,必须具有足够的访问权限。这些权限通常由数据库管理人员授予。
视图可以嵌套,即可以利用从其他视图中检索数据的查询来构造视图。所允许的嵌套层数在不同的DBMS中有所不同(嵌套视图可能会严
重降低查询的性能,因此在产品环境中使用之前,应该对其进行全面测试)。
许多DBMS禁止在视图查询中使用ORDER BY子句。
有些DBMS要求对返回的所有列进行命名,如果列是计算字段,则需要使用别名(关于列别名的更多信息,请参阅第7课)。
视图不能索引,也不能有关联的触发器或默认值。
有些DBMS把视图作为只读的查询,这表示可以从视图检索数据,但不能将数据写回底层表。详情请参阅具体的DBMS文档。
有些DBMS允许创建这样的视图,它不能进行导致行不再属于视图的插入或更新。例如有一个视图,只检索带有电子邮件地址的顾客。如
果更新某个顾客,删除他的电子邮件地址,将使该顾客不再属于视图。这是默认行为,而且是允许的,但有的DBMS可能会防止这种情况 发生。
视图用CREATE VIEW语句来创建
删除视图,可以使用DROP语句,其语法为DROP VIEW viewname。覆盖(或更新)视图,必须先删除它,然后再重新创建。
利用视图简化复杂的联结
用视图重新格式化检索出的数据
用视图过滤不想要的数据
使用视图与计算字段
可以创建存储过程。简单来说,存储过程就是为以后使用而保存的一条或多条SQL语句。可将其视为批文件,虽然它们的作用不仅限于批处理。
通过把处理封装在一个易用的单元中,可以简化复杂的操作(如前面例子所述)。
由于不要求反复建立一系列处理步骤,因而保证了数据的一致性。如果所有开发人员和应用程序都使用同一存储过程,则所使用的代码都是相同的。
这一点的延伸就是防止错误。需要执行的步骤越多,出错的可能性就越大。防止错误保证了数据的一致性。
简化对变动的管理。如果表名、列名或业务逻辑(或别的内容)有变化,那么只需要更改存储过程的代码。使用它的人员甚至不需要知道 这些变化。
这一点的延伸就是安全性。通过存储过程限制对基础数据的访问,减少了数据讹误(无意识的或别的原因所导致的数据讹误)的机会。 因为存储过程通常以编译过的形式存储,所以DBMS处理命令的工作较少,提高了性能。
存在一些只能用在单个请求中的SQL元素和特性,存储过程可以使用它们来编写功能更强更灵活的代码。
换句话说,使用存储过程有三个主要的好处,即简单、安全、高性能。显然,它们都很重要。不过,在将SQL代码转换为存储过程前,也必须
知道它的一些缺陷。
不同DBMS中的存储过程语法有所不同。事实上,编写真正的可移植存储过程几乎是不可能的。不过,存储过程的自我调用(名字以及数 据如何传递)可以相对保持可移植。因此,如果需要移植到别的DBMS,至少客户端应用代码不需要变动。
一般来说,编写存储过程比编写基本SQL语句复杂,需要更高的技能,更丰富的经验。因此,许多数据库管理员把限制存储过程的创建作
为安全措施(主要受上一条缺陷的影响)。
1 | create procedure productpricing() |
用CREATE PROCEDURE productpricing()语句定义。如果存储过程接受参数,它们将在()中列举出来。存储过程的代码位于BEGIN和END语句内,
mysql命令行客户机的分隔符
DELIMITER //告诉命令行实用程序使用//作为新的语句结束分隔符,
1 | CALL productpricing() |
1 | DROP PROCEDURE productpricing; |
1 | create procedure productpricing( |
每个参数必须具有指定的类型,这里使用十进制值(DECIMAL 关键字)。关键字OUT指出相应的参数用来从存储过程传出一个值(返回给调用者)。MySQL支持IN(传递给存储过程)、OUT(从存储过程传出,如这里所用)和INOUT(对存储过程传入和传出)类型的参数。
1 | CALL productpricing(@procelow, @pricehigh, @priceAverage); |
变量名: 所有MySQL变量都必须以@开始。
只有在存储过程内包含业务规则和智能处理时,它们的威力才真正显现出来。
用DECLARE语句定义了两个局部变量。DECLARE要求指定变量名和数据类型,它也支持可选的默认值.
COMMENT关键字 本例子中的存储过程在CREATE PROCEDURE语
句中包含了一个COMMENT值。它不是必需的,但如果给出,将
在SHOW PROCEDURE STATUS的结果中显示。
1 | # 显示用来创建一个存储过程的CREATE语句 |
使用事务处理(transaction processing),通过确保成批的SQL操作要么完全执行,要么完全不执行,来维护数据库的完整
管理事务处理的关键在于将SQL语句组分解为逻辑块,并明确规定数据何时应该回退,何时不应该回退。
1 | # 开始事务 |
ROLLBACK命令用来回退(撤销)MySQL语句
ROLLBACK** 只能在一个事务处理内使用(在执行一条STARTTRANSACTION命令之后)。
一般的MySQL语句都是直接针对数据库表执行和编写的。这就是所谓的隐含提交(implicit commit),即提交(写或保存)操作是自动进行的。
但是,在事务处理块中,提交不会隐含地进行。为进行明确的提交,使用COMMIT语句.
隐含事务关闭 :当COMMIT或ROLLBACK语句执行后,事务会自动关闭(将来的更改会隐含提交)
保留点越多越好可以在SQL代码中设置任意多的保留点,越多越好。为什么呢?因为保留点越多,你就越能灵活地进行回退。
结果集(result set)SQL查询所检索出的结果。
有时,需要在检索出来的行中前进或后退一行或多行,这就是游标的用途所在。
游标(cursor)是一个存储在DBMS服务器上的数据库查询, 它不是一条SELECT语句,而是被该语句检索出来的结果集。
能够标记游标为只读,使数据能读取,但不能更新和删除。
能控制可以执行的定向操作(向前、向后、第一、最后、绝对位置、相对位置等)。
能标记某些列为可编辑的,某些列为不可编辑的。
规定范围,使游标对创建它的特定请求(如存储过程)或对所有请求可访问。
指示DBMS对检索出的数据(而不是指出表中活动数据)进行复制,使数据在游标打开和访问期间不变化。
说明:游标与基于Web的应用
步骤:
在使用游标前,必须声明(定义)它。这个过程实际上没有检索数据,它只是定义要使用的SELECT语句和游标选项。
一旦声明,就必须打开游标以供使用。这个过程用前面定义的SELECT语句把数据实际检索出来。
对于填有数据的游标,根据需要取出(检索)各行。
在结束游标使用时,必须关闭游标,可能的话,释放游标(有赖于具体的DBMS)。
使用DECLARE语句创建游标
创建
使用
约束(constraint) 管理如何插入或处理数据库数据的规则。
包括:主键、外键、唯一约束、检查约束
满足条件:
任意两行的主键值都不相同。
每行都具有一个主键值(即列中不允许NULL值)。
包含主键值的列从不修改或更新。(大多数DBMS不允许这么做,但如果你使用的DBMS允许这样做,好吧,千万别!)
主键值不能重用。如果从表中删除某一行,其主键值不分配给新行。
指定列为主键: PRIMARY KEY
外键是表中的一列,其值必须列在另一表的主键中。外键是保证引用完整性的极其重要部分。
外键有助防止意外删除
主键和唯一约束区别:
检查约束用来保证一列(或一组列)中的数据满足一组指定的条件。检查约束的常见用途有以下几点。
检查最小或最大值。例如,防止0个物品的订单(即使0是合法的数)。
指定范围。例如,保证发货日期大于等于今天的日期,但不超过今天起一年后的日期。
只允许特定的值。例如,在性别字段中只允许M或F。
是什么:触发器是特殊的存储过程,它在特定的数据库活动发生时自动执行。
一般来说,约束的处理比触发器快,因此在可能的时候,应该尽量使用约束。
对数据库管理功能(创建表、更改或删除已存在的表等)的访问;
对特定数据库或表的访问;
访问的类型(只读、对特定列的访问等);
仅通过视图或存储过程对表进行访问;
创建多层次的安全措施,从而允许多种基于登录的访问和控制;
限制管理用户账号的能力。
关键字 | 作用 | 附加说明 |
---|---|---|
SELECT | 要返回的列或表达式 | |
FROM | 从中检索数据的表 | |
WHERE | 指定搜索条件进行过滤(行级过滤) | 范围值检查:BETWEEN xx AND xx 指定条件范围:IN(xx, xx) 否定其后条件:NOT |
GROUP BY | 分组 | 组级过滤:HAVING |
ORDER BY | 输出排序顺序 | 降序:DESC (DESCENDING) 升序(默认):ASC(ASCENDING) |
DISTINCT distinct | ||
IS NULL | 非空检查 | |
AND 、OR | 逻辑操作符 | |
LIKE | ||
distinct
它指示数据库只返回不同的值。
eg:SELECT DISTINCT vend_id FROM Products;
警告:不能部分使用 DISTINCT
DISTINCT关键字作用于所有的列,不仅仅是跟在其后的那一列。例如,你指定SELECT DISTINCT vend_id, prod_price,除非指定的两列完
全相同,否则所有的行都会被检索出来。
源于redis版本 3.2.1,可能和最新版本略有差异。
1 | ######################### 引用 ######################### |
参考:https://oss.redislabs.com/redisbloom/
1 | # branch参数指定克隆的tag。 |
1 | # 设置 |
1 | # 安装依赖 |
1 | auth Cnitsec%4321 |
1 | 7283:M 12 Mar 12:13:33.749 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. |
sysctl -w net.core.somaxconn = 1024
1 | # 修改/etc/sysctl.conf文件,增加一行 |
补充:
net.core.somaxconn是linux中的一个kernel参数,表示socket监听(listen)的backlog上限。
backlog是socket的监听队列,当一个请求(request)尚未被处理或建立时,他会进入backlog。
而socket server可以一次性处理backlog中的所有请求,处理后的请求不再位于监听队列中。
当server处理请求较慢,以至于监听队列被填满后,新来的请求会被拒绝。
所以说net.core.somaxconn限制了接收新 TCP 连接侦听队列的大小。
对于一个经常处理新连接的高负载 web服务环境来说,默认的 128 太小了。大多数环境这个值建议增加到 1024 或者更多。
方法1: 临时设置生效:
sysctl -w vm.overcommit_memory = 1
1 | # 方法2: 永久生效: 修改/etc/sysctl.conf文件,增加一行 |
overcommit_memory参数说明:
设置内存分配策略(可选,根据服务器的实际情况进行设置)
/proc/sys/vm/overcommit_memory
可选值:0、1、2。
0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
2, 表示内核允许分配超过所有物理内存和交换空间总和的内存
注意:redis在dump数据的时候,会fork出一个子进程,理论上child进程所占用的内存和parent是一样的,比如parent占用的内存为8G,这个时候也要同样分配8G的内存给child,如果内存无法负担,往往会造成redis服务器的down机或者IO负载过高,效率下降。所以这里比较优化的内存分配策略应该设置为 1(表示内核允许分配所有的物理内存,而不管当前的内存状态如何)。
1 | .\mysqld.exe --initialize-insecure --user=mysql |
1 | [mysqld] |
关于java中位运算符的使用和理解
‘ & ’ 符号的作用是对运算符的两侧以二进制表达的操作符按位进行‘与’运算。
规则:
只有两个操作数对应位同为1时,结果为1,其余全为0. (或者是只要有一个操作数为0,结果就为0)。
个人理解:在编程中,我们可以认为‘1’代表‘true’,‘0’代表‘false’。那么就可以理解为只有都为‘true’的时候才为‘true’,否则就是‘false’。
举例:
5 & 10 = ?
10 的二进制为:1010
5 的二进制为:0101
则 5 & 10 的二进制为 0000,完整的运算为 5 & 10 = 0
int i = 12; i &= 7; i = ?
‘ &= ’ 的逻辑跟 ‘ += ’ 的处理逻辑是一样的
i &= 7 可以看成 i = i & 7
所以i = 4
‘ | ’ 符号的作用是对运算符两侧以二进制表达的操作符按位分别进行’或’运算。
规则:
只有两个操作数对应位同为1时,结果为1,其余全为0. (或者是只要有一个操作数为1,结果就为1)。
个人理解:在编程中,我们可以认为‘1’代表‘true’,‘0’代表‘false’。那么就可以理解为只要有一个为‘true’的时候就为‘true’,否则就是‘false’。
举例:
5 | 10 = ?
10 的二进制为:1010
5 的二进制为:0101
则 5 | 10 的二进制为 1111,完整的运算为 5 | 10 = 15
int i = 12; i |= 7; i = ?
‘ |= ’ 的逻辑跟 ‘ += ’ 的处理逻辑是一样的
i |= 7 可以看成 i = i | 7
所以i = 15
‘ ^ ’ 符号的作用是对运算符两侧以二进制表达的操作数按位分别进行’异或’运算。
规则:
仅当两个操作数不同一时候。对应的输出结果才为1,否则为0。
个人理解:在编程中,我们可以认为‘1’代表‘true’,‘0’代表‘false’。那么就可以理解为值不相等的时候为‘true’,值相等的时候为‘false’。
举例:
5 ^ 10 = ?
10 的二进制为:1010
5 的二进制为:0101
则 5 ^ 10 的二进制为 1111,完整的运算为 5 ^ 10 = 15
int i = 12; i ^= 7; i = ?
‘ ^= ’ 的逻辑跟 ‘ += ’ 的处理逻辑是一样的
i ^= 7 可以看成 i = i ^ 7
所以i = 11
‘ ~ ’ 符号的作用是将各位数组取反。
规则:
全部的0变为1,1变为0。
个人理解:在编程中,我们可以认为‘1’代表‘true’,‘0’代表‘false’。那么就可以理解为将‘true’变成‘false’,而‘false’变为‘true’。
举例:
~ 10 = ?
10 的二进制为:1010
取反后为:1111 1111 1111 0101
则 1111 1111 1111 0101 的十进制为 -11,完整的运算为 ~ 10 = -11
很多人对负数的二进制的转换很迷惑,在这里为大家讲解下:
因为电脑的世界中只有 ‘ 1 ’ 和 ‘ 0 ’ ,所以在表示正负数的时候是从最高位看的,最高位如果为 ‘ 1 ’ 则为负数,如果是 ‘ 0 ’ 则是正数。
但是如果负数单纯是把最高位变为1的话,在运算中会出现不是我们想要的值。所以引入了:‘原码’,‘反码’,‘补码’。
正数的‘原码’,‘反码’,‘补码’都一样。
负数的‘反码’是对除了符号位(最高位)的‘原码’取反,而‘补码’是对‘反码’ + 1,而计算机所采用的就是‘补码’的方式。
示例:
-11的‘原码’是 : 1000 0000 0000 1011
求出对应的反码 : 1111 1111 1111 0100
求出对应的补码 : 1111 1111 1111 0101
所以在计算机中 ‘ -11 ’ 对应的二进制为 ‘ 1111 1111 1111 0101 ’
‘ << ’ 符号的作用是将一个运算对象的各二进制位全部左移若干位。
规则:
左边的二进制位丢弃,右边补0。
个人理解:左移可以看成是乘以2的多少次方。3 << 3就代表3乘以2的3次方。
举例:
10 << 3 = ?
10 的二进制为:0000 0000 0000 1010
移位后为:0000 0000 0101 0000 (80)
则 10 << 3 = 80
int i = 5; i <<= 4; i = ?
‘ <<= ’ 的逻辑跟 ‘ += ’ 的处理逻辑是一样的
i <<= 4 可以看成 i = i << 4
所以i = 80
‘ >> ’ 符号的作用是将一个运算对象的各二进制位全部右移若干位。
规则:
正数左补0,负数左补1,右边丢弃。
个人理解:正数右移可以看成是跟2的多少次方取模,10 >> 3就代表10跟8取模得1。而负数则需要对应的转换,因为负数进行了补码的操作,所以跟正数的逻辑不同
举例:
10 >> 3 = ?
10 的二进制为:0000 0000 0000 1010
移位后为:0000 0000 0000 0001
则 10 >> 3 = 1
int i = 5; i >>= 4; i = ?
‘ >>= ’ 的逻辑跟 ‘ += ’ 的处理逻辑是一样的
i >>= 4 可以看成 i = i >> 4
所以i = 0
‘ >>> ’ 符号的作用是将一个运算对象的各二进制位全部右移若干位。
规则:
右移后左边空出的位用零来填充。移出右边的位被丢弃。无符号的意思是将符号位当作数字位看待。
个人理解:正数的无符号右移可以看成是跟2的多少次方取模,10 >>> 3就代表10跟8取模得1。而负数的无符号右移是不同的,就不需要再进行转换的操作,-1 >>> 1 = 2147483647
举例:
10 >>> 3 = ?
10 的二进制为:0000 0000 0000 1010
移位后为:0000 0000 0000 0001
则 10 >>> 3 = 1
int i = 5; i >>>= 4; i = ?
‘ >>>= ’ 的逻辑跟 ‘ += ’ 的处理逻辑是一样的
i >>>= 4 可以看成 i = i >>> 4
所以i = 0
[Unit]
区块通常是配置文件的第一个区块,用来定义 Unit 的元数据,以及配置与其他 Unit 的关系。它的主要字段如下。
Description
:简短描述Documentation
:文档地址Requires
:当前 Unit 依赖的其他 Unit,如果它们没有运行,当前 Unit 会启动失败Wants
:与当前 Unit 配合的其他 Unit,如果它们没有运行,当前 Unit 不会启动失败BindsTo
:与Requires
类似,它指定的 Unit 如果退出,会导致当前 Unit 停止运行Before
:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之后启动After
:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之前启动Conflicts
:这里指定的 Unit 不能与当前 Unit 同时运行Condition...
:当前 Unit 运行必须满足的条件,否则不会运行Assert...
:当前 Unit 运行必须满足的条件,否则会报启动失败
[Install]
通常是配置文件的最后一个区块,用来定义如何启动,以及是否开机启动。它的主要字段如下。
WantedBy
:它的值是一个或多个 Target,当前 Unit 激活时(enable)符号链接会放入/etc/systemd/system
目录下面以 Target 名 +.wants
后缀构成的子目录中RequiredBy
:它的值是一个或多个 Target,当前 Unit 激活时,符号链接会放入/etc/systemd/system
目录下面以 Target 名 +.required
后缀构成的子目录中Alias
:当前 Unit 可用于启动的别名Also
:当前 Unit 激活(enable)时,会被同时激活的其他 Unit
[Service]
区块用来 Service 的配置,只有 Service 类型的 Unit 才有这个区块。它的主要字段如下。
Type
:定义启动时的进程行为。它有以下几种值。Type=simple
:默认值,执行ExecStart
指定的命令,启动主进程Type=forking
:以 fork 方式从父进程创建子进程,创建后父进程会立即退出Type=oneshot
:一次性进程,Systemd 会等当前服务退出,再继续往下执行Type=dbus
:当前服务通过D-Bus启动Type=notify
:当前服务启动完毕,会通知Systemd
,再继续往下执行Type=idle
:若有其他任务执行完毕,当前服务才会运行ExecStart
:启动当前服务的命令ExecStartPre
:启动当前服务之前执行的命令ExecStartPost
:启动当前服务之后执行的命令ExecReload
:重启当前服务时执行的命令ExecStop
:停止当前服务时执行的命令ExecStopPost
:停止当其服务之后执行的命令RestartSec
:自动重启当前服务间隔的秒数Restart
:定义何种情况 Systemd 会自动重启当前服务,可能的值包括always
(总是重启)、on-success
、on-failure
、on-abnormal
、on-abort
、on-watchdog
TimeoutSec
:定义 Systemd 停止当前服务之前等待的秒数Environment
:指定环境变量