绝对路径:如/etc/init.d
当前目录和上层目录:./../
主目录:~/
切换目录:cd
查看当前进程:ps
执行退出:exit
查看当前路径:pwd
清屏:clear
退出当前命令:ctrl+c彻底退出
执行睡眠:ctrl+z挂起当前进程fg恢复后台
查看当前用户id:”id“:查看显示目前登陆账户的uid和gid及所属分组及用户名
查看指定帮助:如man adduser这个很全而且有例子;adduser--help这个告诉你一些常用参数;infoadduesr;
ls执行的功能:列出指定目录中的目录,以及文件
哪些参数以及区别:a所有文件l详细信息,包括大小字节数,可读可写可执行的权限等
软链接:ln-s slinksource
硬链接:lnlinksource
创建目录:mkdir
创建文件:典型的如touch,vi也可以创建文件,其实只要向一个不存在的文件输出,都会创建文件
复制文件:cp
文件权限修改:chmod
格式如下:
$chmodu+x file给file的属主增加执行权限
$chmod751file给file的属主分配读、写、执行(7)的权限,给file的所在组分配读、执行(5)的权限,给其他用户分配执行(1)的权限
$chmodu=rwx,g=rx,o=xfile上例的另一种形式
$chmod=rfile为所有用户分配读权限
$chmod444file同上例
$chmoda-wx,a+rfile同上例
$chmod-Ru+rdirectory递归地给directory目录下所有文件和子目录的属主分配读的权限
vi文件名#编辑方式查看,可修改
cat文件名#显示全部文件内容
more文件名#分页显示文件内容
less文件名#与more相似,更好的是可以往前翻页
tail文件名#仅查看尾部,还可以指定行数
head文件名#仅查看头部,还可以指定行数
写文件命令:vi 向屏幕输出带空格的字符串:echo hello world
终端:/dev/tty 黑洞文件:/dev/null
mv mv
cp cp-r????
rm rm-r rmdir
“?”可替代单个字符。
“*”可替代任意多个字符。
方括号“[charset]”可替代charset集中的任何单个字符,如[a-z],[abABC]
wc命令-c统计字节数。-l统计行数。-w统计字数。
是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。Grep [string STRING] filename
grep[^string]filename
(1)、不可中断状态:进程处于睡眠状态,但是此刻进程是不可中断的。不可中断,指进程不响应异步信号。
(2)、暂停状态/跟踪状态:向进程发送一个SIGSTOP信号,它就会因响应该信号而进入TASK_STOPPED状态;当进程正在被跟踪时,它处于TASK_TRACED这个
特殊的状态。“正在被跟踪”指的是进程暂停下来,等待跟踪它的进程对它进行操作。
(3)、就绪状态:在run_queue队列里的状态
(4)、运行状态:在run_queue队列里的状态
(5)、可中断睡眠状态:处于这个状态的进程因为等待某某事件的发生(比如等待socket连接、等待信号量),而被挂起
(6)、zombie状态(僵尸):父亲没有通过wait系列的系统调用会顺便将子进程的尸体(task_struct)也释放掉
(7)、退出状态
一般都是使用 & 在命令结尾来让程序自动运行。(命令后可以不追加空格)
ps-ef(systemv输出)
ps-auxbsd格式输出
ps-ef|grep pid
jobs -l
把后台任务调到前台执行 fg
把停下的后台任务在后台执行起来 bg
kill [-s <信息名称或编号>][程序] 或 kill [-l <信息编号>]
kill-9 pid
Kill -l
find <指定目录> <指定条件> <指定动作>
whereis 加参数与文件名
locate 只加文件名
find 直接搜索磁盘,较慢。
find / -name "string*"
查找自己所在的终端信息:who am i
查看当前谁在使用该主机:who
history
df-hl
netstat
ifconfig
env
\u显示当前用户账号
\h显示当前主机名
\W只显示当前路径最后一个目录
\w显示当前绝对路径(当前用户目录会以~代替)
$PWD显示当前全路径
\$显示命令行’$'或者’#'符号
\#:下达的第几个命令
\d:代表日期,格式为week day month date,例如:"MonAug1"
\t:显示时间为24小时格式,如:HH:MM:SS
\T:显示时间为12小时格式
\A:显示时间为24小时格式:HH:MM
\v:BASH的版本信息
如export PS1=’[\u@\h\w\#]\$‘
whereis[-bfmsu][-B<目录>...][-M<目录>...][-S<目录>...][文件...]
补充说明:whereis指令会在特定目录中查找符合条件的文件。这些文件的烈性应属于原始代码,二进制文件,或是帮助文件。
-b只查找二进制文件。
-B<目录>只在设置的目录下查找二进制文件。
-f不显示文件名前的路径名称。
-m只查找说明文件。
-M<目录>只在设置的目录下查找说明文件。
-s只查找原始代码文件。
-S<目录>只在设置的目录下查找原始代码文件。
-u查找不包含指定类型的文件。
which指令会在PATH变量指定的路径中,搜索某个系统命令的位置,并且返回第一个搜索结果。
-n指定文件名长度,指定的长度必须大于或等于所有文件中最长的文
件名。
-p与-n参数相同,但此处的包括了文件的路径。
-w指定输出时栏位的宽度。
-V显示版本信息
which只能查可执行文件
whereis只能查二进制文件、说明文档,源文件等
alias la='ls-a'
0.11核提供的内存管理函数大部分在memery.c中,我将其中的函数从功能上分为三类:内存的分配与释放、页异常处理和内存初始化。第一类主要包括单个物理页的操作和页表的操作,单个物理页的操作就是一个物理页的申请、映射和释放;页表操作主要是多个页表的释放、复制。第二类主要是处理缺页异常和写保护异常的中断处理函数。第三类就是一个函数负责内存的初始化工作。
一、内存的分配与释放
1、get_free_page():在主内存区中申请一空闲物理页。
首先扫描mem_map[],从末端向前寻找值为0的元素,找到后将它的值置成1,并根据这个元素的在mem_map[]中的索引值得到物理页的地址,再将物理页中的4K字节清零,最后返回物理地址。
2、free_page():释放指定物理地址处的物理页。
在验证了这个地址的有效性之后,根据它换算出对应的页地址:(addr-1M)/4K,再利用此地址值作为索引在mem_map[]中找到对应项,将其清零。
3、free_page_tables():释放从指定线性地址开始的若干个页表以及它对应的物理页。
先判断传入的线性地址是否有效,即是否在4MB边界上,然后就算出它所占的页目录项的个数和第一个目录项的地址,接着从第一个目录项开始,对于可用的目录项(也就是p=1:存在对应的页表)就根据目录项得到页表的地址,从而释放页表中的所有记录着的物理页(free_page)并将此页表项清零,之后释放掉这个页表本身所占的物理页并将它对应的页目录项清零。直到处理完最后一个页目录项。最后刷新TLB。
4、copy_page_tables():复制指定线性地址开始的若干个页表到指定的目标线性地址处。
这个函数是fork一个进程时候用到的,它让子进程共享父进程的物理内存。在验证了地址的边界性之后,换算出页目录项表中的源目录项起始地址和目标目录项的起始地址以及要复制的页目录项的个数。然后开始复制工作:首先申请一页内存存放新页表,然后设置对应的页目录项,再循环复制源页表中各页表项到新页表中(对于内核进程只复制前160项就行,因为内核模块不超过640K),并将各个页表项设为只读,最后根据各个页的物理地址在mem_map[]中将此页对应的元素的值加1(表示引用次数加1)。然后循环这样的复制工作直到复制完所有的页表。
5、put_page():将一物理页映射到指定的线性地址空间处。
也就是根据线性地址找到对应的页表项,将这个页表项中的值设为这个物理页的物理地址。这个函数一般在get_free_page()后使用。在验证了地址有效性之后,先根据线性地址的高10位换算出页目录项的地址,在从页目录项中得到页表地址,再根据线性地址的中间10位得到页表项地址。最后将在这个页表项中设置它所映射的物理页地址和一些页信息。
6、get_empty_page():get_free_page()和put_page()的结合。
gcc-c hello.c -o hello.o gcc -E hello.c -o hello.i
创建一个静态库: #gcc-c hello.c -o hello.o # ar cr libmyhello.a
hello.o
使用静态库: gcc -ohello main.c -L. -lmyhello
(注意,gcc 会在静态库名前加上前缀lib,然后追加扩展名.a 得到的静态库
文件名来查找静态库文件。)
后缀为: .a
命名规范:前缀”lib“、库名和后缀3 部分组成,其中动态链接库以.so
最为后缀,静态链接库通常以.a作为后缀。
区别:静态库的代码在编译时就拷贝的应用程序中,这样的优点是节省编
译时间。
动态链接库时程序在开始运行后调用库函数时才被载入。
nm:
#nm test
08049f10 d _DYNAMIC
08049ff4 d _GLOBAL_OFFSET_TABLE_
080486f0 t _GLOBAL__I_main
第一列:当前符号的地址
第二列:当前符号的类型
第三列:当前符号的名称
nm 的作用:
(1)判断指定程序中有没有定义指定的符号(比较常用的方式:nm -C test
| grep symbol)
//加上-C,可让第二列易于阅读,如t _GLOBAL__I_main ----》》》main
( 2 ) 解决程序编译时undefinedreference 的错误,以及mutiple
definition 的错误
(3)查看某个符号的地址,以及在进程空间的大概位置(bss, data, text
区,具体可以通过第二列的类型来判断)
ldd:
#ldd test
linux-gate.so.1 => (0xffffe000)
libz.so.1 => /lib/libz.so.1 (0xb7f8c000)
libpthread.so.0 => /lib/libpthread.so.0 (0xb7f75000)
第一列:程序需要依赖什么库
第二列: 系统提供的与程序需要的库所对应的库
第三列:库加载的开始地址
ldd 的作用:
(1) 通过对比第一列和第二列,我们可以分析程序需要依赖的库和系统实
际提供的,是否相匹配
(2) 通过观察第三列,我们可以知道在当前的库中的符号在对应的进程的
地址空间中的开始位置
创建动态库:gcc -chello.c -o hello.o gcc -shared -fPCI -o
libmyhello.so hello.o
动态库的后缀名:.so
使用动态库:gcc -ohello main.c -L. -lmyhello
动态库命名规范:前缀”lib“、库名和后缀3 部分组成,其中动态链接库
以.so 最为后缀,静态链接库通常以.a作为后缀。
默认查找路径:/usr/lib/lib (静态库的默认路径为当前目录)
动态库显示连接所使用的系统库: ???????
没找到合适的答案
/proc 该文件夹下,有各种以PID 命名的文件夹,分别存放每个进程的信息
STDIN STDOUT STDERR
Write read open close
int fcntl(int fields, intcmd,... /* int arg */);
1.复制一个现有的描述符(cmd = F_DUPFD).
2.获得/设置文件描述符标记(cmd = F_GETFD || F_SETFD).
3.获得/设置文件状态标记(cmd = F_GETFL || F_SETFL).
4.获得/设置异步I/O 所有权(cmd = F_GETOWN || F_SETOWN).
5.获得/设置记录锁(cmd = F_GETLK, F_SETLK || F_SETLKW).
fork 与clone 的区别:
fork()函数复制时将父进程的所以资源都通过复制数据结构进行了复
制,然后传递给子进程,
所以fork()函数不带参数;
clone()函数则是将部分父进程的资源的数据结构进行复制,复制哪些资
源是可选择的这个可以通过参数设定,所以clone()函数带参数,没有复制的资
源可以通过指针共享给子进程;
//int clone(int (*fn)(void *), void *child_stack, int flags, void*arg)
//fn 为函数指针,此指针指向一个函数体,即想要创建进程的静态程序;
//child_stack 为给子进程分配系统堆栈的指针;arg 就是传给子进程的参数;
flags 为要复制资源的标志:
fork()和vfork()的区别:
1). fork :子进程拷贝父进程的数据段,代码段
vfork:子进程与父进程共享数据段
2). fork :父子进程的执行次序不确定
vfork 保证子进程先运行,在调用exec 或exit 之前与父进程数据是共享
的,在它调用exec 或exit 之后父进程才可能被调度运行。如果在调用这两个
函数之前子进程依赖于父进程的进一步动作,则会导致死锁。
孤儿进程 僵尸进程
//暂时停止目前进程的执行,直到有信号来到或子进程结束。status 中
存的是子进程的结束状态(exit(3))
pid_t waitpid(pid_t pid, int *statloc, int options); //如果成功
返回进程ID,0(使用WNOHANG 选项),如果出错返回-1.
Pid:
从参数的名字pid 和类型pid_t 中就可以看出,这里需要的是一个
进程ID。但当pid 取不同的值时,在这里有不同的意义。
pid>0 时,等待进程ID 等于pid 的子进程,不管其它已经有多少子
进程运行结束退出了,只要指定的子进程还没有结束,waitpid 就会一直等下去。
pid=-1 时,等待任何一个子进程退出,没有任何限制,此时waitpid
和wait 的作用一模一样。
pid=0 时,等待同一个进程组中的任何子进程,如果子进程已经加入
了别的进程组,waitpid不会对它做任何理睬。
pid<-1 时,等待一个指定进程组中的任何子进程,这个进程组的ID
等于pid 的绝对值。
Options:
options 提供了一些额外的选项来控制waitpid,目前在Linux 中只
支持WNOHANG 和WUNTRACED 两个选项,这是两个常数,
可以用"|"运算符把它们连接起来使用,比如:
ret=waitpid(-1,NULL,WNOHANG | WUNTRACED);
返回值:
当正常返回的时候,waitpid返回收集到的子进程的进程ID;如果
设置了选项WNOHANG,而调用中waitpid 发现没有已退出的子进程
可收集,则返回0; 如果调用中出错,则返回-1,这时errno 会被
设置成相应的值以指示错误所在; 当pid 所指示的子进程不存在,或
此进程存在,但不是调用进程的子进程,waitpid 就会出错返回,这
时errno 被设置为ECHILD;
fork 父子共享的:
打开的文件
实际用户ID、实际组ID、有效用户ID、有效组ID
添加组ID
进程组ID
对话期ID
控制终端。
设置-用户-ID 标志和设置-组-ID 标志
当前工作目录
根目录
文件方式创建屏蔽字
信号屏蔽和排列
对任一打开文件描述符的在执行时关闭标志
环境
连接的共享存储段(共享内存)
资源限制
fork 父子区别:
fork 的返回值
进程ID
不同的父进程ID
子进程的tms_utime,tms_stime,tms_cutime以及tms_ustime
设置为0
父进程设置的锁,子进程不继承
子进程的未决告警被清除
子进程的未决信号集设置为空集
SIGINT SIGCHLD SIGALRM
sig_t signal(int signum,sig_t handler); // 错误返回
SIG_ERR
int sigaction(int signum,const struct sigaction *act ,struct
sigaction *oldact);
int kill(pid_t pid, int sig);
unsigned int alarm(unsigned int seconds);
int raise(int sig); //向自身发信号
非可靠信号, 表现在信号不支持排队,信号可能会丢失, 比如发送
多次相同的信号, 进程只能收到一次.
可靠信号, 表现在信号支持排队, 不会丢失, 发多少次, 就可以收
到多少次.
信号值位于[SIGRTMIN,SIGRTMAX] 区间的都是可靠信号.
信号值小于SIGRTMIN的都是非可靠信号.
int sigprocmask(int how, const sigset_t *restrict set, sigset_t
*restrict oldset);
SigSuspend:于在接收到某个信号之前,临时用mask 替换进程的信号掩
码,并暂停进程执行,直到收到信号为止。
//可参看sigsuspend 详解.doc
sigpending:sigpending()会将被搁置的信号集合由参数set 指针返回.
返回值执行成功则返回0, 如果有错误则返回-1.
// 参看linux 可靠信号与非可靠信号
当一个信号的信号处理函数执行时,如果进程又接收到了该信号,该信
号会自动被储存而不会中断信号处理函数的执行,直到信号处理函数执行完毕再重新调用相应的处理函数。但是如果在信号处理函数执行时进程收到了其它类型的信号,该函数的执行就会被中断
信号;管道;消息队列;共享内存;信号量;socket;
select的本质是采用32个整数的32位,即32*32= 1024来标识,fd值为1-1024。当fd的值超过1024限制时,就必须修改FD_SETSIZE的大小。这个时候就可以标识32*max值范围的fd。
对于单进程多线程,每个线程处理多个fd的情况,select是不适合的。
1.所有的线程均是从1-32*max进行扫描,每个线程处理的均是一段fd值,这样做有点浪费
2.1024上限问题,一个处理多个用户的进程,fd值远远大于1024
所以这个时候应该采用poll,
poll传递的是数组头指针和该数组的长度,只要数组的长度不是很长,性能还是很不错的,因为poll一次在内核中申请4K(一个页的大小来存放fd),尽量控制在4K以内
epoll还是poll的一种优化,返回后不需要对所有的fd进行遍历,在内核中维持了fd的列表。select和poll是将这个内核列表维持在用户态,然后传递到内核中。但是只有在2.6的内核才支持。
epoll更适合于处理大量的fd ,且活跃fd不是很多的情况,毕竟fd较多还是一个串行的操
#include<sys/types.h>
#include<sys/socket.h>
intgetsockopt(int sock, int level, int optname, void *optval,
socklen_t*optlen);
intsetsockopt(int sock, int level, int optname, const void
*optval,socklen_t optlen);
参数:
sock:将要被设置或者获取选项的套接字。
level:选项所在的协议层。
optname:需要访问的选项名。
optval:对于getsockopt() , 指向返回选项值的缓冲。对于
setsockopt(),指向包含新选项值的缓冲。
optlen:对于getsockopt(),作为入口参数时,选项值的最大长度。作
为出口参数时,选项值的实际长度。对于setsockopt(),现选项的长度。
返回说明:
成功执行时,返回0。失败返回-1,errno 被设为以下的某个值
EBADF:sock 不是有效的文件描述词
EFAULT:optval 指向的内存并非有效的进程空间
EINVAL:在调用setsockopt()时,optlen 无效
ENOPROTOOPT:指定的协议层不能识别选项
ENOTSOCK:sock 描述的不是套接字
参数详细说明:
level 指定控制套接字的层次.可以取三种值:
1)SOL_SOCKET:通用套接字选项.
2)IPPROTO_IP:IP 选项.
3)IPPROTO_TCP:TCP 选项.
optname 指定控制的方式(选项的名称),我们下面详细解释
optval 获得或者是设置套接字选项.根据选项名称的数据类型进行转换
结束线程?主线程等待子线程结束时使用的函数?
Linux 下最常用的是遵循POSIX 标准的pthread 线程库。pthread 的实现是
通过系统调用clone()这一Linux 特有的系统调用来实现。
extern int pthread_create __P ((pthread_t *__thread, __const
pthread_attr_t *__attr,void *(*__start_routine) (void *), void*__arg));
extern void pthread_exit __P ((void *__retval)) __attribute__
((__noreturn__));
extern int pthread_join __P ((pthread_t __th, void
**__thread_return));
一个线程默认的状态是joinable,如果线程是joinable 状态,当线程
函数自己返回退出时或pthread_exit时都不会释放线程所占用堆栈和线程描述
符(总计8K 多)。只有当你调用了pthread_join 之后这些资源才会被释放。
若是unjoinable 状态的线程,这些资源在线程函数退出时或
pthread_exit时自动会被释放。
unjoinable属性可以在pthread_create 时指定,或在线程创建后在
线程中pthread_detach自己, 如:pthread_detach(pthread_self()),将状态
改为unjoinable 状态,确保资源的释放。如果线程状态为joinable,需要在之
后适时调用pthread_join.