vfs(virtual filesystem)是内核给予用户空间、用于对内核文件操作的接口。
举个例子: sys_write()
或者sys_open()
.
- super block
关于文件系统的高级元数据的容器,存在于磁盘上,管理文件系统的参数:块的数量、空闲块和根索引节点,这是在磁盘上;内存中,每一个list??维护一个super_block 块。
这个块存放文件系统本身的结构信息。不同版本的Unix实现的具体内容不一样。
- i-node
linux使用这个数据结构管理文件系统的所有对象。该数据结构使用slab进行内存分配。里面有很多的列表,其中一个指向引用该inode的dentry;只存在于内存中;
存放有关文件的属性,比如大小,文件所有者和最近修改时间等
- dentry
文件系统中有一个根dentry,这也是唯一一个没有父对象的dentry.所有其他dentry都有父对象,并且一部分还有子对象。在这个结构体内,有一个super_block,注释说是这是该目录的root。该结构体仅能存在文件系统内存中,而不能存放在磁盘上,存放在磁盘上的,最终是inode。
- file
内核中打开的每个文件都是一个file对象。
内核中处理一个文件系统。重要的函数 syn(_fs());
内核中处理一个文件。
内核中处理一个目录项。
内核中处理一个打开的文件。
VFS的内部由一个调度层(提供文件系统抽象)和许多缓存(用于改善文件系统操作的性能 )。VFS中动态管理的两个对象是dentry和inode.缓存这两个对象,用来实现后面的功能 。
` /etc/init.d/mysql stop `
(您可能有其它的方法,总之停止mysqld的运行就可以了)
mysqld --skip-grant-tables &
`mysql -u root
mysql> update mysql.user set password=PASSWORD('newpassword') where User='root';
mysql> flush privileges;
mysql> quit
尤其注意这里的格式,你必须保没有警告。</br>
重新启动MySQL
/etc/init.d/mysql restart
就可以使用新密码 newpassword 登录了。
不要在原子上下文中休眠
禁止中断时,也不能休眠
要确保有进程能唤醒自己
4.休眠被唤醒之后仍要检查等待的条件是否为真,否则重新继续休眠.
我们休眠的代码必须能够唤醒(wake_up),我们需要维护一个称为等待队列的数据结构. 等待队列就是一个进程链表,其中包含了等待了某个特定事件的所有进程. linux维护一个”等待队列头”来管理,wait_queue_head_t,定义在<linux/wait.h>
struct __wait_queue_head {
spinlock_t lock;
struct list_head task_list;
};
typedef struct __wait_queue_head wait_queue_head_t;
这里结构体前面的”__“是系统调用的函数.
DECLARE_WAIT_QUEUE_HEAD(name)
/* This is the method to initializer */
#define DECLARE_WAIT_QUEUE_HEAD(name) {
wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
}
#define __WAIT_QUEUE_HEAD_INITIALIZER(name) { \
.lock = __SPIN_LOCK_UNLOCKED(name.lock) \
.task_list = { &(name).task_list, &(name).tsak_list}
}
DECLARE_WAIT_QUEUE_HEAD(name);
色块内的是方法,这里,我把相关的代码放在了一起,以便于理解.
wait_queue_head_t my_queue;
init_waitqueue_head(&my_queue);
/* from here */
struct __wit_queue_head {
spinlock_t lock;
struct list_head task_list;
};
typedef struct __wait_queue_head wait_queue_head_t;
linux 中最简单的休眠方式是下面的宏:
wait_event(queue, condition); //uninterruptible sleep
wait_event_interruptible(queue, condition); //返回非0值表示 休眠被信号中断
在这两个Macro实现中,分别有一个might_sleep()
的使用.而且后者
在实现上比前者多了个int __ret = 0
;
wait_event_timeout(queue, condition, timeout);
wait_event_interruptible_timeout(queue, condition, timeout);
不得不说一下这个宏,上面这四个宏中都牵扯上它了.代码注释是这么说的:
might_sleep - annotation for function that can sleep
queue 是等待队列头,传值方式,condition是任意一个布尔表达式,在休眠前后多次 对condition求值,为真则唤醒.
void wake_up(wait_queue_head_t *queue);
void wake_up_interruptible(wait_queue_head_t *queue);
实际上,一般是wait_event
和wake_up,
wait_event_interruptible和
wake_
u_interruptible`成对使用
(linux 中关于信号的资源)![http://www.thegeekstuff.com/2012/03/linux-signals-fundamentals/]
资源(http://www.linuxprogrammingblog.com/all-about-linux-signals?page=3)
信号就是一个软中断(software interrupts)。 一个健壮的程序必须需要处理信号,信号是向应用程序传递异步事件的方式。
一个用户按下ctrl+c 就是向另一个程序发送信号
用户通过Crtl-C、Crtl-\等键或者通过驱动终端程序来请求内核产生信号。
当进程执行出错时,内核给进程发送一个信号,比如,非法存取段、浮点数溢出、 或者一个非法的机器指令。内核也利用信号通知进程特事件的发生。
一个进程可以通过系统调用kill给另一个进程发送信号。一个进程可以可以和另一个 进程通过信号通信。
由进程的某个操作产生的信号被称为同步信号,例如,被零除;像用户击键这样的进程外 的事件引起的信号称之为异步信号。
使用以下调用来恢复默认处理
signal(SIGINT, SIG_DFL);
这是这类信号处理行为的最普遍的,有SIGTERM、SIGQUIT、SIGPIPE、SIGUSR1、SIGUSR2
有SIGSEGV、SIGILL、SIGABRT这个信号。
比如这个SIGCHLD
SIGSTOP使进程悬停(suspend)然后使用SIGCOND继续(shell中的ctrl-z)
程序可以通过以下调用来告诉内核,它需要忽略SIGINT的信号
signal(SIGINT, SIG_IGN);
如果产生像除以0的致命错误、SIGKILL和SIGSTOP不能被忽略。
后两个信号供root用户拥有杀死任何进程的权利。
程序在接收到SIGINT后,调用一个恢复设置的函数
signal(SIGALRM, handler);
补充一下最后一点,捕捉信号的函数应该是可重入的。在解释这个原因前,让我们首先了解下什么是可重入。一个可重入的函数是一个函数在执行的过程的可以因为某些原因被停止下来(比如中断或者信号),在完成了某项任务后可以返回继续执行原来的程序。原因很简单,当一个程序正在执行的时候,信号发生(捕捉另一个信号),进程转而执行其他的程序,如果这个时候正好宿主程序的全局变量和被呼叫的程序的变量同名的话,那么,当子进程执行完毕后返回宿主进程中,会产生意想不到的结果
可靠信号就是实时信号
非可靠信号就是非实时信号,凡位于[SIGRTMIN, SIGRTMAX]区间的都是可靠信号.
非可靠信号一般都有明确的用途和含义,可靠信号则可以让用户自己定义使用.
#include<signal.h>
void (*signal(int signum, void (*handler))(int))(int);