今天用了一下Ubuntu
,第一感觉就是在root
账户的使用方面同RHEL
和SuSE
不大一样:
(1)安装Ubuntu
过程没有设置root
密码的步骤。需要你使用创建的账户登录后,使用sudo passwd
命令设置root
密码。
(2)似乎不能使用root
账户进行ssh
远程连接(更新:解决办法在这里。):
$ ssh root@10.10.249.177
要使用你创建的账户:
$ ssh nan@110.10.249.177
今天用了一下Ubuntu
,第一感觉就是在root
账户的使用方面同RHEL
和SuSE
不大一样:
(1)安装Ubuntu
过程没有设置root
密码的步骤。需要你使用创建的账户登录后,使用sudo passwd
命令设置root
密码。
(2)似乎不能使用root
账户进行ssh
远程连接(更新:解决办法在这里。):
$ ssh root@10.10.249.177
要使用你创建的账户:
$ ssh nan@110.10.249.177
The infix style of writing an expression is just a convenience; we can also write an expression in prefix form, where the operator precedes its arguments. To do this, we must enclose the operator in parentheses.
举例如下:
ghci> 3 ^ 4
81
ghci> (^) 3 4
81
ghci> ^ 3 4
<interactive>:68:1: parse error on input ‘^’
SystemTap
提供了系统调用(syscall
)的probe
:
# stap -L "syscall.*"
syscall.accept sockfd:long addr_uaddr:long addrlen_uaddr:long name:string flags:long flags_str:string argstr:string
syscall.accept4 sockfd:long addr_uaddr:long addrlen_uaddr:long flags:long name:string flags_str:string argstr:string
syscall.access name:string pathname:string mode:long mode_str:string argstr:string $filename:long int $mode:long int
syscall.acct name:string filename:string argstr:string $name:long int
......
# stap -L "syscall.*.return"
syscall.accept.return
syscall.accept4.return
syscall.access.return name:string retstr:string $return:long int $filename:long int $mode:long int
syscall.acct.return name:string retstr:string $return:long int $name:long int
......
关于syscall probe
的变量定义:
Each probe alias defines a variety of variables. Look at the tapset source code to find the most reliable source of variable definitions. Generally, each variable listed in the standard manual page is available as a script-level variable. For example, syscall.open exposes file name, flags, and mode. In addition, a standard suite of variables is available at most aliases, as follows:
argstr: A pretty-printed form of the entire argument list, without parentheses.
name: The name of the system call.
retstr: For return probes, a pretty-printed form of the system call result.
以syscall.open
和syscall.open.return
为例:
# stap -L "syscall.open"
syscall.open filename:string mode:long __nr:long name:string flags:long argstr:string $filename:long int $flags:long int $mode:long int
# stap -e 'probe syscall.open{printf("argstr is %s, __nr is %d\n", argstr, __nr)}'
argstr is "/sys/fs/cgroup/systemd/system.slice/systemd-udevd.service/cgroup.procs", O_RDONLY|O_CLOEXEC, __nr is 2
argstr is "/etc/passwd", O_RDONLY|O_CLOEXEC, __nr is 2
argstr is "/proc/self/maps", O_RDONLY|O_CLOEXEC, __nr is 2
......
# stap -e 'probe syscall.open{printf("filename is %s, name is %s, flags is 0x%x, mode is 0x%x\n", filename, name, flags, mode)}'
filename is "/sys/fs/cgroup/systemd/system.slice/systemd-udevd.service/cgroup.procs", name is open, flags is 0x80000, mode is 0x1b6
filename is "/proc/interrupts", name is open, flags is 0x0, mode is 0x1b6
filename is "/proc/stat", name is open, flags is 0x0, mode is 0x1b6
......
# stap -e 'probe syscall.open{printf("filename is 0x%x, $flags is 0x%x, $mode is 0x%x\n", $filename, $flags, $mode)}'
filename is 0x1a658f0, $flags is 0x80000, $mode is 0x1b6
filename is 0x7f750760b26e, $flags is 0x0, $mode is 0x1b6
filename is 0x7f750760b291, $flags is 0x0, $mode is 0x1b6
filename is 0x7ffcf45d73d0, $flags is 0x0, $mode is 0x1b6
......
# stap -L "syscall.open.return"
syscall.open.return __nr:long name:string retstr:string $return:long int $filename:long int $flags:long int $mode:long int
# stap -e 'probe syscall.open.return{printf("__nr is %d, name is %s, retstr is %s\n", __nr, name, retstr)}'
__nr is 2, name is open, retstr is 13
__nr is 2, name is open, retstr is 3
__nr is 2, name is open, retstr is 3
__nr is 2, name is open, retstr is -2 (ENOENT)
__nr is 2, name is open, retstr is -2 (ENOENT)
__nr is 2, name is open, retstr is -2 (ENOENT)
......
# stap -e 'probe syscall.open.return{printf("fiilename is 0x%x, $flags is 0x%x, $mode is 0x%x\n", $filename, $flags, $mode)}'
fiilename is 0x7f750760b26e, $flags is 0x0, $mode is 0x1b6
fiilename is 0x7f750760b291, $flags is 0x0, $mode is 0x1b6
fiilename is 0x7ffcf45d73d0, $flags is 0x0, $mode is 0x1b6
fiilename is 0x7ffcf45d73d0, $flags is 0x0, $mode is 0x1b6
fiilename is 0x7ffcf45d73d0, $flags is 0x0, $mode is 0x1b6
......
下面这个find
命令列出当前目录下的*.stp
文件:
# find . -name '*.stp' -exec ls {} \;
./Documents/one.stp
./Documents/two.stp
关于find
命令的“-exec COMMAND \;
”:
find
-exec COMMAND \;
Carries out COMMAND on each file that find matches. The command sequence terminates with ; (the “;” is escaped to make certain the shell passes it to find literally, without interpreting it as a special character).
If COMMAND contains {}, then find substitutes the full path name of the selected file for “{}”.
;
的作用是标示命令完结,\;
是让shell
把;
原封不动地传给find
命令。而{}
会使用查找出来的文件的全路径名。
参考资料:
16.2. Complex Commands。
在Kconfig
文件中:
config A
depends on B
select C
它的含义是:CONFIG_A
配置与否,取决于CONFIG_B
是否配置。一旦CONFIG_A
配置了,CONFIG_C
也自动配置了。
SystemTap
追踪user-space
程序时需要安装user-space
程序的debug-info
包。举个例子:
# stap -d /bin/ls --ldd -e 'probe process("ls").function("xmalloc") {print_usyms(ubacktrace())}' -c "ls /"
semantic error: while resolving probe point: identifier 'process' at <input>:1:7
source: probe process("ls").function("xmalloc") {print_usyms(ubacktrace())}
^
semantic error: no match (similar functions: malloc, calloc, realloc, close, mbrtowc)
Pass 2: analysis failed. [man error::pass2]
安装coreutils-debuginfo
包:
# zypper in coreutils-debuginfo
Loading repository data...
Reading installed packages...
Resolving package dependencies...
The following NEW package is going to be installed:
coreutils-debuginfo
The following package is not supported by its vendor:
coreutils-debuginfo
1 new package to install.
Overall download size: 2.1 MiB. Already cached: 0 B. After the operation, additional 18.6 MiB will be used.
Continue? [y/n/? shows all options] (y): y
Retrieving package coreutils-debuginfo-8.22-9.1.x86_64 (1/1), 2.1 MiB ( 18.6 MiB unpacked)
Retrieving: coreutils-debuginfo-8.22-9.1.x86_64.rpm ...................................................................[done (105.3 KiB/s)]
Checking for file conflicts: ........................................................................................................[done]
(1/1) Installing: coreutils-debuginfo-8.22-9.1 ......................................................................................[done]
再次执行上述命令:
# stap -d /bin/ls --ldd -e 'probe process("ls").function("xmalloc") {print_usyms(ubacktrace())}' -c "ls /"
bin boot dev etc home lib lib64 lost+found mnt opt proc root run sbin selinux srv sys tmp usr var
0x4114a0 : xmalloc+0x0/0x20 [/usr/bin/ls]
0x411674 : xmemdup+0x14/0x30 [/usr/bin/ls]
0x40ee4a : clone_quoting_options+0x2a/0x40 [/usr/bin/ls]
0x403828 : main+0xa58/0x2140 [/usr/bin/ls]
0x7fad37eefb05 : __libc_start_main+0xf5/0x1c0 [/lib64/libc-2.19.so]
0x404f39 : _start+0x29/0x30 [/usr/bin/ls]
0x4114a0 : xmalloc+0x0/0x20 [/usr/bin/ls]
0x411674 : xmemdup+0x14/0x30 [/usr/bin/ls]
0x40ee4a : clone_quoting_options+0x2a/0x40 [/usr/bin/ls]
0x403887 : main+0xab7/0x2140 [/usr/bin/ls]
0x7fad37eefb05 : __libc_start_main+0xf5/0x1c0 [/lib64/libc-2.19.so]
0x404f39 : _start+0x29/0x30 [/usr/bin/ls]
0x4114a0 : xmalloc+0x0/0x20 [/usr/bin/ls]
0x4039e4 : main+0xc14/0x2140 [/usr/bin/ls]
0x7fad37eefb05 : __libc_start_main+0xf5/0x1c0 [/lib64/libc-2.19.so]
.....
ioctl
系统调用的函数原型:
int ioctl(int fd, unsigned long cmd, ...);
In a real system, however, a system call can’t actually have a variable number of arguments. System calls must have a well-defined prototype, because user programs can access them only through hardware “gates.” Therefore, the dots in the prototype represent not a variable number of arguments but a single optional argument, traditionally identified as char *argp . The dots are simply there to prevent type checking during compilation. The actual nature of the third argument depends on the specific control command being issued (the second argument).
...
并不是代表可变参数,而只是一个可选参数,...
在这里防止编译时进行类型检查。
目前在struct file_operations
结构体中已不再有ioctl
成员:
int (*ioctl) (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
取而代之是unlocked_ioctl
和compat_ioctl
:
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
unlocked_ioctl
代替ioctl
,而compat_ioctl
用在32
位程序运行在64
位操作系统上调用ioctl
系统调用。
ioctl
的命令是32-bit
长,包含以下4
个字段:
---------------------------------------------------------------
| dirction(2/3-bit)|size(14/13-bit)| type(8-bit)|number(8-bit)|
各个字段定义:
type
The magic number. Just choose one number (after consulting ioctl-number.txt) and use it throughout the driver. This field is eight bits wide ( IOCTYPEBITS ).number
The ordinal (sequential) number. It’s eight bits ( IOCNRBITS ) wide.direction
The direction of data transfer, if the particular command involves a data transfer. The possible values are IOCNONE (no data transfer), IOCREAD , IOCWRITE , and IOCREAD|IOCWRITE (data is transferred both ways). Data transfer is seen from the application’s point of view; IOCREAD means reading from the device, so the driver must write to user space. Note that the field is a bit mask, so IOC READ and IOCWRITE can be extracted using a logical AND operation.size
The size of user data involved. The width of this field is architecture dependent, but is usually 13 or 14 bits. You can find its value for your specific architecture in the macro IOCSIZEBITS . It’s not mandatory that you use the size field—the kernel does not check it—but it is a good idea. Proper use of this field can help detect user-space programming errors and enable you to implement backward compatibility if you ever need to change the size of the relevant data item. If you need larger data structures, however, you can just ignore the size field. We’ll see how this field is used soon.
相关的macro
定义:
extern unsigned int __invalid_size_argument_for_IOC;
#define _IOC_TYPECHECK(t) \
((sizeof(t) == sizeof(t[1]) && \
sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
sizeof(t) : __invalid_size_argument_for_IOC)
#define _IOC(dir,type,nr,size) \
(((dir) << _IOC_DIRSHIFT) | \
((type) << _IOC_TYPESHIFT) | \
((nr) << _IOC_NRSHIFT) | \
((size) << _IOC_SIZESHIFT))
/* used to create numbers */
#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
/* used to decode ioctl numbers.. */
#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
参考资料:
The new way of ioctl();
Linux Kernel ioctl(), unlockedioctl(), and compatioctl();
Advanced Char Driver Operations。
(1)
Because strings are lists, we can use list functions on them.
举例如下:
> "Hello " ++ "world"
"Hello world"
(2)
:
用来连接一个元素和list
,++
连接两个list
:
>let list = [1, 2, 3, 4]
> print list
[1,2,3,4]
> [5] : list
<interactive>:23:1:
Non type-variable argument in the constraint: Num [t]
(Use FlexibleContexts to permit this)
When checking that ‘it’ has the inferred type
it :: forall t. (Num t, Num [t]) => [[t]]
> 5 : list
[5,1,2,3,4]
(3)
Ranges are a way of making lists that are arithmetic sequences of elements that can be enumerated. Numbers can be enumerated. One, two, three, four, etc. Characters can also be enumerated. The alphabet is an enumeration of characters from A to Z. Names can’t be enumerated. What comes after “John”?
举例如下:
> [1 .. 20]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
也可以指定元素之间的“步长”(2
和4
之间差2
):
> [2, 4 .. 20]
[2,4,6,8,10,12,14,16,18,20]
另外,cycle
循环一个list
:
cycle takes a list and cycles it into an infinite list. If you just try to display the result, it will go on forever so you have to slice it off somewhere.
> take 10 (cycle [1,2,3])
[1,2,3,1,2,3,1,2,3,1]
> take 12 (cycle "LOL ")
"LOL LOL LOL "
repeat
循环一个元素
:
repeat takes an element and produces an infinite list of just that element. It’s like cycling a list with only one element.
> take 10 (repeat 5)
[5,5,5,5,5,5,5,5,5,5]
也可以使用replicate
函数:
replicate function if you want some number of the same element in a list.
> replicate 10 5
[5,5,5,5,5,5,5,5,5,5]
(4)
list
最后一个元素后面不能再跟,
:
> [1,2]
[1,2]
> [1,2,]
<interactive>:12:6: parse error on input ‘]’
(5)
There’s a special type, () , that acts as a tuple of zero elements. This type has only one value, which is also written () . Both the type and the value are usually pronounced “unit.” If you are familiar with C, () is somewhat similar to void.
(6)fst
和snd
这两个函数只能操作包含两个元素的tuple
:
> :type fst
fst :: (a, b) -> a
> :type snd
snd :: (a, b) -> b
(7)
The list [1,2,3] in Haskell is actually shorthand for the list 1:(2:(3:[])), where [] is the empty list and : is the infix operator that adds its first argument to the front of its second argument (a list). (: and [] are like Lisp’s cons and nil, respectively.) Since : is right associative, we can also write this list as 1:2:3:[].
以下摘自plka:
Linux employs a hierarchical scheme in which each process depends on a parent process. The kernel starts the init program as the first process that is responsible for further system initialization actions and display of the login prompt or (in more widespread use today) display of a graphical login interface. init is therefore the root from which all processes originate, more or less directly.
init
进程是Linux
运行的第一个进程,是其它所有进程的“祖先”。
sinit展示了一个最简单的init
进程实现:初始化服务和等待清理子进程。