Algebraic data type
可以拥有多个value constructor
。比如Bool
类型就是一种algebraic data type
:
data Bool = False | True
每个value constructor
可以有0
个或多个参数。
使用data
关键字定义的数据类型,其实都是algebraic data type
,只不过其只包含了一个value constructor
。
Algebraic data type
可以拥有多个value constructor
。比如Bool
类型就是一种algebraic data type
:
data Bool = False | True
每个value constructor
可以有0
个或多个参数。
使用data
关键字定义的数据类型,其实都是algebraic data type
,只不过其只包含了一个value constructor
。
Linux kernel
中针对shared memory
有两个重要的配置项:shmmax
和shmall
:
shmmax
定义了一次分配shared memory
的最大长度,单位是byte
:
# cat /proc/sys/kernel/shmmax
18446744073692774399
shmall
定义了一共能分配shared memory
的最大长度,单位是page
:
最大“shared memory” = shmall(cat /proc/sys/kernel/shmall) * pagesize(getconf PAGE_SIZE)
以shmmax
为例,介绍一下修改值的方法:
(1)现在系统shmmax
的值:
# sysctl -a | grep shmmax
kernel.shmmax = 18446744073692774399
(2)修改shmmax
的值:
# echo "536870912" > /proc/sys/kernel/shmmax
# sysctl -a | grep shmmax
kernel.shmmax = 536870912
可以看到值发生了变化。但是重启系统以后,shmmax
又变回之前的值。如果要让值永久生效,可以使用下列方法:
# echo "kernel.shmmax = 536870912" >> /etc/sysctl.conf
# sysctl -a | grep shmmax
kernel.shmmax = 18446744073692774399
# sysctl -p
kernel.shmmax = 536870912
# sysctl -a | grep shmmax
kernel.shmmax = 536870912
另外,关于如何设置shmall
和shmmax
的值,也可以参考这个脚本。
参考资料:
The Mysterious World of Shmmax and Shmall;
Configuring SHMMAX and SHMALL for Oracle in Linux;
What is shmmax, shmall, shmmni? Shared Memory Max。
使用data
关键字来定义一种新的数据类型(data type
):
data StudentInfo = Student Int String
deriving (Show)
StudentInfo
是type constructor
,也是这种新type
的名字,所以首字母必须大写。
Student
是value constructor
(有时也称之为data constructor
)的名字,它的首字母也必须大写(可以把它看做是首字母大写的函数),作用是用来创建StudentInfo
这种type
的值。在Student
后面的Int
和String
是StudentInfo
这种type
的component(
有时也称作field
或parameter
)
,其作用类似于其它编程语言中结构体成员。
type constructor
只用在type declaration
和type signature
中,而value constructor
只用在实际的代码中。因此二者的使用是相互独立的,可以让type constructor
和value constructor
拥有相同的名字,实际编码中基本也是这样做的:
data Student = Student Int String
deriving (Show)
也可以使用type
关键字为已有的类型定义一个同义词(type synonym
):
type SI = StudentInfo
type synonym
也可以为一个冗长的类型取一个短名字,举例如下:
type SI = (Int, String)
看一下take
函数的type signature
:
ghci> :type take
take :: Int -> [a] -> [a]
这表明它有两个参数,返回值是一个list
。“->
”是右相关(right-associative
),因此实际上也可以把take
函数的type signature
写成这样:
ghci> :type take
take :: Int -> ([a] -> [a])
因此也可以这样理解take
函数:它有一个Int
参数,返回值是另一个函数。这个函数的参数和返回类型是同一个类型的list
。
在RHEL
系统中注册和使用subscription
是两个过程:
NOTE: With Red Hat Subscription-Manager, registration and utilization of a subscription is actually a two-part process. First register a system, then apply a subscription.
可以使用下面命令一次完成两个过程:
# subscription-manager register --username <username> --password <password> --auto-attach
在我的RHEL 7.2
系统上执行上述命令:
# subscription-manager register --username=xxxx --password=xxxx --auto-attach
Registering to: subscription.rhn.redhat.com:443/subscription
The system has been registered with ID: 333486bb-xxxxxx
Installed Product Current Status:
Product Name: Red Hat Enterprise Linux Server
Status: Subscribed
然后检查状态:
# subscription-manager list
+-------------------------------------------+
Installed Product Status
+-------------------------------------------+
Product Name: Red Hat Enterprise Linux Server
Product ID: 69
Version: 7.2
Arch: x86_64
Status: Subscribed
Status Details:
Starts: 06/29/2015
Ends: 06/28/2016
接下来就可以使用“yum install
”,“yum update
”等命令安装和更新软件了,非常方便。
参考资料:
How to Register and Enable Red Hat Subscription, Repositories and Updates for RHEL 7.0 Server;
How to register and subscribe a system to the Red Hat Customer Portal using Red Hat Subscription-Manager;
RHEL : Register Subscription。
Haskell
中对表达式的计算使用的是Lazy evaluation
(也称之为nonstrict evaluation
):即只有表达式的值真正需要时,才会被计算。Haskell
中把用来跟踪还没有计算的表达式的记录称之为trunk
。
参考自stackoverflow:
Mostly because it can be more efficient — values don’t need to be computed if they’re not going to be used. For example, I may pass three values into a function, but depending on the sequence of conditional expressions, only a subset may actually be used. In a language like C, all three values would be computed anyway; but in Haskell, only the necessary values are computed.
It also allows for cool stuff like infinite lists. I can’t have an infinite list in a language like C, but in Haskell, that’s no problem. Infinite lists are used fairly often in certain areas of mathematics, so it can be useful to have the ability to manipulate them.
Lazy evaluation
的优点:高效(延迟执行代码),支持像infinite lists
这样的cool stuff
。
Containerizer
类(定义在src/slave/containerizer/containerizer.hpp
)是所有Containerizer
的抽象父类。除了默认的构造函数和一个什么都没做的析构函数,其只实现了create
和resources
方法。create
方法代码如下(v0.26
版本):
Try<Containerizer*> Containerizer::create(
const Flags& flags,
bool local,
Fetcher* fetcher)
{
if (flags.isolation == "external") {
LOG(WARNING) << "The 'external' isolation flag is deprecated, "
<< "please update your flags to"
<< " '--containerizers=external'.";
Try<ExternalContainerizer*> containerizer =
ExternalContainerizer::create(flags);
if (containerizer.isError()) {
return Error("Could not create ExternalContainerizer: " +
containerizer.error());
}
return containerizer.get();
}
// TODO(benh): We need to store which containerizer or
// containerizers were being used. See MESOS-1663.
// Create containerizer(s).
vector<Containerizer*> containerizers;
foreach (const string& type, strings::split(flags.containerizers, ",")) {
if (type == "mesos") {
Try<MesosContainerizer*> containerizer =
MesosContainerizer::create(flags, local, fetcher);
if (containerizer.isError()) {
return Error("Could not create MesosContainerizer: " +
containerizer.error());
} else {
containerizers.push_back(containerizer.get());
}
} else if (type == "docker") {
Try<DockerContainerizer*> containerizer =
DockerContainerizer::create(flags, fetcher);
if (containerizer.isError()) {
return Error("Could not create DockerContainerizer: " +
containerizer.error());
} else {
containerizers.push_back(containerizer.get());
}
} else if (type == "external") {
Try<ExternalContainerizer*> containerizer =
ExternalContainerizer::create(flags);
if (containerizer.isError()) {
return Error("Could not create ExternalContainerizer: " +
containerizer.error());
} else {
containerizers.push_back(containerizer.get());
}
} else {
return Error("Unknown or unsupported containerizer: " + type);
}
}
if (containerizers.size() == 1) {
return containerizers.front();
}
Try<ComposingContainerizer*> containerizer =
ComposingContainerizer::create(containerizers);
if (containerizer.isError()) {
return Error(containerizer.error());
}
return containerizer.get();
}
默认情况下,containerizers
的type
是mesos
,所以会调用MesosContainerizer::create
来生成containerizer
。关于resources
方法,参考Mesos笔记 (5)—— 资源。
我使用的OS
是CentOS 7.1
,需要安装lxc
和lxc-templates
。安装后的模板在/usr/share/lxc/templates
目录下:
# ls
lxc-alpine lxc-archlinux lxc-centos lxc-debian lxc-fedora lxc-openmandriva lxc-oracle lxc-sshd lxc-ubuntu-cloud
lxc-altlinux lxc-busybox lxc-cirros lxc-download lxc-gentoo lxc-opensuse lxc-plamo lxc-ubuntu
接下来以CentOS
为模板创建一个container
:
lxc-create -t centos --name cn-centos
临时的root
密码存在/var/lib/lxc/cn-01/tmp_root_pass
:
# cat /var/lib/lxc/cn-centos/tmp_root_pass
Root-cn-centos-EXb6bB
启动container
:
# lxc-start -n cn-centos
停止container
:
# lxc-stop -n cn-centos
Mesos
的Framework
,Master
和Slave
之间使用http
协议传递消息。参考下图:
由于Transfer-Encoding
是chunked
格式,所以在http message body
开始部分会包含data
长度:0x44
,也就是68
个字节。另外,data
的编码使用protobuf
协议,也是key-value
格式,具体编码请参考这里。
参考资料:
《HTTP:The Definitive Guide》笔记(2)—— messages;
HTTP – What does ‘Transfer-Encoding : Chunked’ mean?。
LXC is a userspace interface for the Linux kernel containment features. Through a powerful API and simple tools, it lets Linux users easily create and manage system or application containers.
The linux containers, lxc, aims to use these new functionalities to provide a userspace container object which provides full resource isolation and resource control for an application or a system.
Linux container
技术的目标是为应用程序或系统提供完整的资源隔离和控制。LXC
项目通过提供一组API
接口和工具,可以让其他程序方便地使用Linux container
技术。
The container technology is actively being pushed into the mainstream linux kernel. It provides the resource management through the control groups aka process containers and resource isolation through the namespaces.
Linux container
技术cgroups(control groups)
和namespaces
实现。两者的功能如下:
cgroups = limits how much you can use;
namespaces = limits what you can see (and therefore use)
Cgroups
限制了你能够拥有的资源,而namespces
限制了你能够看到的资源。
参考资料:
LXC;
Anatomy of a Container: Namespaces, cgroups & Some Filesystem Magic。