kk Blog —— 通用基础


date [-d @int|str] [+%s|"+%F %T"]
netstat -ltunp
sar -n DEV 1

freeBSD9.2 安装 && 允许root用户用SSH登录

http://forums.freebsd.org/showthread.php?t=36579

Issue:
Here is the error message that I’ve got:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Code:

cd0 at umass-sim0 bus 0 scbus3 target 0 lun 0
cd0: <ASUS SDRW-08D2S-U B302> Removable CD-ROM SCSI-0 device
cd0: 40.000MB/s transfers
cd0: cd present [1166275 x 2048 byte records]Mounting from cd9660:/dev/iso9660/FREEBSD_INSTALL failed with error 19.

Loader variables:
	vfs.root.mountfrom=cd9660:/dev/iso9660/FREEBSD_INSTALL
	vfs.root.mountfrom.option=ro

Manual root filesystem specification:
	<fstype>:<device> [option]
	    Mount <device> using filesystem <fstype>
	    and with the specified (optional) option list.

	eg. ufs:/dev/da0s1a
	    zf:tank

The system seems to recognize the DVD drive but is unable to mount the media correctly.

You need to get a boot prompt and disable ACPI support before booting:
这两句好像没效果

1
2
# set debug.acpi.disabled ="hostres"
# boot

The solution is actually in the FreeBSD 9 errata (section 3)

1
mountroot> cd9660:/dev/cd0  用这句通过

这句不只道可不可以:

1
mountroot> cd9660:/iso9660/FREEBSD_INSTALL

二 FreeBSD 允许root用户用SSH登录

修改freebsd可以用sshd权限用户登录ssh
在/etc/ssh/sshd_config最后中加入

1
2
3
PermitRootLogin yes #允许root登录
PermitEmptyPasswords no #不允许空密码登录
PasswordAuthentication yes # 设置是否使用口令验证。

FreeBSD SSH配置详解 首先vi编辑/etc/inetd.conf,去掉ssh前的#,保存退出 (开启监听ssh服务)
编辑/etc/rc.conf
最后加入:sshd_enable=“yes"即可

激活sshd服务:

1
#/etc/rc.d/sshd start

用下面命令检查服务是否启动,在22端口应该有监听。

1
#netstat -an ## check port number 22

最后

vi /etc/ssh/sshd_config

1
2
3
4
5
6
7
8
9
10
...
Subsystem sftp /usr/libexec/sftp-server
IgnoreRhosts yes
IgnoreUserKnownHosts yes
PrintMotd yes
StrictModes no
RSAAuthentication yes
PermitRootLogin yes #允许root登录
PermitEmptyPasswords no #不允许空密码登录
PasswordAuthentication yes # 设置是否使用口令验证。

记得修改完配置文件后,重新启动sshd服务器(/etc/rc.d/sshd restart)即可。
几点补充说明

1
2
3
4
5
6
7
8
9
10
11
1,如果重启后还是不行请重新载入sshd_config 文件
/etc/rc.d/sshd reload
2,如果出现using keyboard-interactive authentication
password:
请确认PasswordAuthentication是否已经改成yes
另外如果客户端是putty那么请确认"尝试'智能键盘'认证(SSH-2)"的勾是否有去掉
3,如果是使用root帐号登陆
请确认密码是否为空
空密码无法登陆
4请确认是否有安装SSH
sysinstall>>>configure>>>networking>>>sshd是否的勾是否有打上

__builtin_return_address获得程序运行栈

gcc的编译特性使用__builtin_return_address(level)打印出一个函数的堆栈地址。其中 level代表是堆栈中第几层调用地址,__builtin_return_address(0)表示第一层调用地址,即当前函数,__builtin_return_address(1)表示第二层。如代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

void f()
{
	printf("%p,%p" , __builtin_return_address(0), __builtin_return_address(1));
	//printk("Caller is %pS\n", __builtin_return_address(0));
}

void g()
{
	f();
}
int main()
{
	g();
}

分别打印出函数f()和g() 的函数地址,我们通过objdump 出来的文件去查找打印出来的函数地址,这样就能看到调用的函数名了。

编译期间求值

编译期求阶乘

c++ 中的模板可以用来计算一些值,在编译的时候就是实现计算,而不是运行的时候。

求阶乘 n!,一般 me 们会写个这样的程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
long Factorial(long n)
{
	return n == 0 ? 1 : n*Factorial(n-1);
}

int main()
{
	long fac=1, n=20;
	for(int i=1; i<=n; ++i)fac *= i;
	std::cout << "20! = " << fac << " " << Factorial(20) << std::endl;
	return 0;
}

现在使用模板技术,类似于递归的方法求 20 !。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>

template<int N>
class Factorial{
public:
	static const long value = N*Factorial<N-1>::value;
};

template<>
class Factorial<0>{
public:
	static const long value = 1;
};

int main()
{
	std::cout << "20! = " << Factorial<20>::value << std::endl;
	return 0;
}

说明:
template 通常用来参数化类型,通常 class T 或是 typename T(T 用来代替一个类型的名字),不过也可以带一个整型参数 N (貌似规定只能是整型)。
template <> 是用来特殊指定一些情形,比如上面给的 Factorial<0> 指定 N = 0 时的情形,这有点像递归中的 if(n==0) return 1;
class 类中可以带有 static const 变量,这种变量可以在类内初始化(只能是整型);当然既是 const 变量,又是 static 变量;
Factorila<20> 实际是一个类,而 ::value 是其 static 变量;在生成Factorila<20> 的时候同时生成了众多的Factorila ( N >0 && N < 20)类;

更多例子
模板类,或是模版函数,或是模板成员函数,都是编译器根据程序的实际情况而生成的,需要什么就生成什么,不需要就不生成。上面的例子中, 程序中使用 Factorial<20> 这个类,就生成这个类,因为 Factorial<20> 依赖 Factorial<19> 所以又生成 Factorial<19> ,这样一直依赖下去,直到 Factorial<0>( me 们已经指定了)。因为是编译期生成,也是编译器求值,所以实际程序中只能使用 static const 类似的 —— 常量,而不能使用普通的 int n。所以,模板元编程中,么发使用循环,只能类似递归的技术。
通常 me 们会将递归程序转换为循环程序,实际上循环程序基本也都可以递归解决。(是不是一定呢?O__O"…)
求斐波那契数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>

template <long N>
struct Fibonacci{
	static const long value = Fibonacci<N-1>::value + Fibonacci<N-2>::value;
};

template<>
struct Fibonacci<0>{
	static const long value = 0;
};

template<>
struct Fibonacci<1>{
	static const long value = 1;
};

int main()
{
	std::cout << Fibonacci<12>::value << std::endl;
	return 0;
}

第 12 个斐波那契数是 144,这是唯一一个 Fib(n) = n*n 的数。 求 1+2+3+…+n

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>

template <long N>
struct Sum{
	static const long value = N+Sum<N-1>::value;
};

template<>
struct Sum<1>{
	static const long value = 1;
};

int main()
{
	std::cout << Sum<100>::value << std::endl;
	return 0;
}

这个和 n! 的用法基本一样。

constexpr编译期求值

模板只是在编译的时候完成工作的一种方法,实际上上面的模板元编程也只是在编译期求了一些常量而已;为了简化使用模板进行元编程的难度,c++11 引入了 constexpr 关键字 —— 声明常量或是函数,实现在编译期求值。上面的三个程序都可以大大简化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>

constexpr long factorial(long n)
{
	return n<=1 ? 1 : n*factorial(n-1);
}
constexpr long fibonacci(long n)
{
	return n<=1 ? n : fibonacci(n-1)+fibonacci(n-2);
}
constexpr long sum(long n)
{
	return n<=1 ? n : n+sum(n-1);
}

int main()
{
	std::cout << "10! F(12) 1+2+...+100 => " << factorial(10) << " " << fibonacci(12) << " " << sum(100) << std::endl;
	return 0;
}

不用多数,看应该看得懂神马意思,要提的就是 constexpr 都是编译的时候求值。