读linux内核访问文件部分代码笔记

访问文件

访问文件的几种模式:

  1. 规范模式:规范模式打开文件后,标志O_SYNC,与O_DIRECT清零,而且他的内容是由系统调用read()和write()来存取。
  2. 同步模式:同步模式下文件打开后,标志O_SYNC置1或稍后由系统调用fcntl()对其置1.这个标志只影响写操作,他将阻塞调用进程,直到数据被有效的写入磁盘。
  3. 内存映射模式:内存映射模式下打开文件后,应用程序发出系统调用mmap()将文件映射到内存中。
  4. 直接I/O模式:直接I/O模式下文件打开后,标志O_DIRECT置1,任何读写操作都将数据在用户态地址空间与磁盘间直接传送而不通过页高速缓存。
  5. 异步模式:异步模式就是数据传输请求并不阻塞调用进程,而是在后台执行,同时应用程序继续他的正常执行。

读文件:

读文件是基于页的,内核总是一次传送几个完整的数据页。读数据主要完成的是一个查找数据位置的操作。如果进程发出read()系统调用来读取一些字节,而这些数据还不在RAM中,那么内核就要分配一个新页框,并且使用文件的适当部分来填充这个页,把该页加入页高速缓存,最后把所请求的字节拷贝到进程地址空间中(还是将一个页面拷贝到进程地址空间中)。

Mm/filemap.c(do_generic_file_read(struct file *filp, loff_t *ppos,
        read_descriptor_t *desc))

函数分析:

static void do_generic_file_read(struct file *filp, loff_t *ppos,
        read_descriptor_t *desc)
{
    /*1、获得要读取的文件对应的address_space对象;他的地址存放在filp->filp->f_mapping*/
    struct address_space *mapping = filp->f_mapping;
    /*2、获得地址空间对象的所有者,即索引节点对象,它将拥有条虫了文件数据的页面。他的地址存放在address_space对象的host字段中。*/
    struct inode *inode = mapping->host;
    struct file_ra_state *ra = &filp->f_ra;
    pgoff_t index;
    pgoff_t last_index;
    pgoff_t prev_index;
    unsigned long offset;      /* offset into pagecache page */
    unsigned int prev_offset;
    int error;

    /*3、把文件看作细分的数据页,并从文件指针*ppos导出第一个请求字节所在的页的逻辑号,即地址空间中的页索引,并把它存放在index局部变量中*/
    index = *ppos >> PAGE_CACHE_SHIFT;
    prev_index = ra->prev_pos >> PAGE_CACHE_SHIFT;
    prev_offset = ra->prev_pos & (PAGE_CACHE_SIZE-1);
    last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
    /*把第一个请求字节在页内的偏移量存放在offset局部变量中*/
    offset = *ppos & ~PAGE_CACHE_MASK;
    /*4、开始一个循环来读入包含请求字节的所有页,要去数据的字节数存放在read_descriptor_t描述符desc的count字段中,在单独的循环期间,函数通过执行下边的步骤来传送一个数据页*/
    for (;;) {
        struct page *page;
        pgoff_t end_index;
        loff_t isize;
        unsigned long nr, ret;

        /*a、调用cond_resched()来检查当前进程的标志TIF_NEED_RESCHED。如果该标志置位,则调用函数schedule()分配处理器资源*/
        cond_resched();
find_page:
        /*b、调用find_get_page(),并传入address_space对象的指针及索引值做为参数;他将查找页高速缓存以找到包含所请求数据的页描述符 */ 
        page = find_get_page(mapping, index);
        /*c、如果find_get_page()反回NULL指针,则所请求的页不再页高速缓存中,及cache没有命中,如果发生这种情况则会执行如下步骤:*/
        if (!page) {
/*(1)、强制执行同步的预读操作*/
            page_cache_sync_readahead(mapping,
                    ra, filp,
                    index, last_index - index);
            /*(2)、再次调用find_get_page(),查找页高速缓存以找到包含所请求数据的页描述符*/
            page = find_get_page(mapping, index);
            /*(3)、如果还是没有在页高速缓存中找到包含请求数据的页描述符,则跳到标签:no_cached_page */
            if (unlikely(page == NULL))
                goto no_cached_page;
        }
        /*d、如果有预读的页,则调用page_cache_async_readahead ()函数读取这些页面*/
        if (PageReadahead(page)) {
            page_cache_async_readahead(mapping,
                    ra, filp, page,
                    index, last_index - index);
        }
        /*e、如果程序执行到此,说明页面已经在页高速缓存区中,这时需要检查页所存的数据是否是最新的,如果页面中所存数据没有更新则跳到:page_not_up_to_date */
        if (!PageUptodate(page)) {
            /*f、页面中的数据是无效的,就必须从磁盘读取,函数通过trylock_page ()函数获取对页的互斥访问*/
            if (inode->i_blkbits == PAGE_CACHE_SHIFT ||
                    !mapping->a_ops->is_partially_uptodate)
                goto page_not_up_to_date;
            if (!trylock_page(page))
                goto page_not_up_to_date;
            /* Did it get truncated before we got the lock? */
            if (!page->mapping)
                goto page_not_up_to_date_locked;
            if (!mapping->a_ops->is_partially_uptodate(page,
                                desc, offset))
                goto page_not_up_to_date_locked;
            unlock_page(page);
        }
page_ok:
        /*
         * i_size must be checked after we know the page is Uptodate.
         *
         * Checking i_size after the check allows us to calculate
         * the correct value for "nr", which means the zero-filled
         * part of the page is not copied back to userspace (unless
         * another truncate extends the file - this is desired though).
         */

        isize = i_size_read(inode);
        end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
/*g、如果index超出文件中包含的页数(该数是通过将inode对象的i_size字段的值除以4096得到的),那么它将减少页的引用计数器,并跳出循环到out。这种情况发生在这个正被本进程读的文件同时又其他进程正在删减它的时候*/
        if (unlikely(!isize || index > end_index)) {
            page_cache_release(page);
            goto out;
        }
        /* nr is the maximum number of bytes to copy from this page */
        /*h、将应被拷入用户态缓冲区的页中字数放在局部变量nr中,这个值应该等于页的大小,除非offset非零(这只发生在读请求的首尾页时)或请求数据不全在该文件中*/
        nr = PAGE_CACHE_SIZE;
        if (index == end_index) {
            nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
            if (nr <= offset) {
                page_cache_release(page);
                goto out;
            }
        }
        nr = nr - offset;

        /* If users can be writing to this page using arbitrary
         * virtual addresses, take care about potential aliasing
         * before reading the page on the kernel side.
         */
        if (mapping_writably_mapped(mapping))
            flush_dcache_page(page);

        /*
         * When a sequential read accesses a page several times,
         * only mark it as accessed the first time.
         */
        /*i、调用mark_page_access()将标志PG_referenced或PG_active置位,从而表示该页正在被访问并且不应该被换出。如果同一文件在do_generic_file_read()的后续执行中要读几次,那么这个步骤只在第一次读时执行*/
        if (prev_index != index || offset != prev_offset)
            mark_page_accessed(page);
        prev_index = index;

        /*
         * Ok, we have the page, and it's up-to-date, so
         * now we can copy it to user space...
         *
         * The file_read_actor routine returns how many bytes were
         * actually used..
         * NOTE! This may not be the same as how much of a user buffer
         * we filled up (we may be padding etc), so we can only update
         * "pos" here (the actor routine has to update the user buffer
         * pointers and the remaining count).
         */
        /**************************************************
        *     j、现在已经有了page并且已经将其中的数据更新,是时候将页面中的数据拷贝到用户缓冲区的时候了,为此调用了file_read_actor函数,该函数执行以下几部:
        *   (1):调用kmap(),该函数为处于高端内存中的页建立永久的内核映射
        *   (2):调用__copy_to_user(),该函数把页中的数据拷贝到用户态地址空间。这个操作在访问用户态地址空间时如有缺页异常将会阻塞进程。
        *   (3):调用kunmap()来释放页的任意永久内核映射.
        *   (4):更新read_descriptor_t描述符的count、written和buf字段。
        *
        *       int file_read_actor(read_descriptor_t *desc, struct page *page,
        *                   unsigned long offset, unsigned long size)
        *       {
        *           char *kaddr;
        *           unsigned long left, count = desc->count;
        *       
        *           if (size > count)
        *               size = count;
        *       
        *           if (!fault_in_pages_writeable(desc->arg.buf, size)) {
        *               kaddr = kmap_atomic(page);
        *               left = __copy_to_user_inatomic(desc->arg.buf,
        *                               kaddr + offset, size);
        *               kunmap_atomic(kaddr);
        *               if (left == 0)
        *                   goto success;
        *           }
        *       
        *           kaddr = kmap(page);
        *           left = __copy_to_user(desc->arg.buf, kaddr + offset, size);
        *           kunmap(page);

        *           if (left) {
        *               size -= left;
        *               desc->error = -EFAULT;
        *           }
        *       success:
        *           desc->count = count - size;
        *           desc->written += size;
        *           desc->arg.buf += size;
        *           return size;
        *       }
        *********************************************/
        ret = file_read_actor(desc, page, offset, nr);
        /*k根据传入用户态缓冲区的有效字节数来更新局部变量index和count。一般情况下,如果页的最后一个字节已经拷贝到用户态缓冲区,那么index的值加1而offset的值清零;否则,index的值不变而offset的值被设为已拷贝到用户态缓冲区的字节数*/
        offset += ret;
        index += offset >> PAGE_CACHE_SHIFT;
        offset &= ~PAGE_CACHE_MASK;
        prev_offset = offset;

        /*l、减少页描述符的引用计数器,如果read_descriptor_t描述符放的count字段不为0,那么文件中还有其他数据要读跳到循环头部开始读取下一个页面,否则跳出循环*/
        page_cache_release(page);
        if (ret == nr && desc->count)
            continue;
        goto out;

page_not_up_to_date:
        /* Get exclusive access to the page ... */
        error = lock_page_killable(page);
        if (unlikely(error))
            goto readpage_error;

/*m、现在的页已经由进程锁定。然而,另一个进程也许会在上一步之前已经从页高速缓存中删除该页,那么就要检查页描述符的mapping字段是否为NULL。在这种情况下,将调用unlock_page()来解锁页,减少它的引用计数,并调回循环开头重读一个页*/
page_not_up_to_date_locked:
        /* Did it get truncated before we got the lock? */
        if (!page->mapping) {
            unlock_page(page);
            page_cache_release(page);
            continue;
        }

        /* Did somebody else fill it already? */
        if (PageUptodate(page)) {
            unlock_page(page);
            goto page_ok;
        }

readpage:
        /*
         * A previous I/O error may have been due to temporary
         * failures, eg. multipath errors.
         * PG_error will be set again if readpage fails.
         */
        ClearPageError(page);
        /* Start the actual read. The read will unlock the page. */
        /*n、现在正真的I/O操作可以开始了,调用文件的address_space对象的readpage方法。相应的函数会负责激活磁盘到页之间的I/O数据传递。*/
        error = mapping->a_ops->readpage(filp, page);

        if (unlikely(error)) {
            if (error == AOP_TRUNCATED_PAGE) {
                page_cache_release(page);
                goto find_page;
            }
            goto readpage_error;
        }

        /*o、如果标志PG_ uptodate还没有置位,则他会等待直到调用lock_page_killable ()函数后页被有效读入,该页从f被锁定等待从磁盘中读取数据,一旦读操作完成就被解锁。当前进程在I/O数据传输完成时才停止睡眠*/
        if (!PageUptodate(page)) {
            error = lock_page_killable(page);
            if (unlikely(error))
                goto readpage_error;
            if (!PageUptodate(page)) {
                if (page->mapping == NULL) {
                    /*
                     * invalidate_mapping_pages got it
                     */
                    unlock_page(page);
                    page_cache_release(page);
                    goto find_page;
                }
                unlock_page(page);
                shrink_readahead_size_eio(filp, ra);
                error = -EIO;
                goto readpage_error;
            }
            unlock_page(page);
        }

        goto page_ok;

readpage_error:
        /* UHHUH! A synchronous read error occurred. Report it */
        desc->error = error;
        page_cache_release(page);
        goto out;

/*p、如果所请求的页不再页高速缓存中,则执行下列步骤*/
no_cached_page:
        /*
         * Ok, it wasn't cached, so we need to create a new
         * page..
         */
        /*(1)、分配一个新页,并插入该页描述符到页高速缓存中*/
        page = page_cache_alloc_cold(mapping);
        if (!page) {
            desc->error = -ENOMEM;
            goto out;
        }
        /*插入新页描述符到LRU链表*/
        error = add_to_page_cache_lru(page, mapping,
                        index, GFP_KERNEL);
        if (error) {
            page_cache_release(page);
            if (error == -EEXIST)
                goto find_page;
            desc->error = error;
            goto out;
        }
        goto readpage;
    }

/*5、所有请求的或者说可以独到的数据已读完。函数更新预读数据结构filp->f_ra来标记数据已被顺序从文件读入*/
out:
    ra->prev_pos = prev_index;
    ra->prev_pos <<= PAGE_CACHE_SHIFT;
    ra->prev_pos |= prev_offset;

    /*把index*4096+offset值付给*ppos,从而保存以后调用read()和write()进行顺序访问的位置*/
    *ppos = ((loff_t)index << PAGE_CACHE_SHIFT) + offset;
    /*调用file_accessed ()函数把当前时间存放在文件的索引节点对象的i_atime字段中,并把它标记为脏后返回*/
    file_accessed(filp);
}

写入文件

Write()系统调用设计把数据从调用进程的用户态地址空间中移动到内核数据结构中,再移动到磁盘上。每个write()方法都是一个过程,该过程主要标识写操作涉及的磁盘块,把数据从用户态地址空间拷贝到页高速缓存的某些页中,然后把这些页中的缓冲区标记成脏。

/**
 * __generic_file_aio_write - write data to a file
 * @iocb:   IO state structure (file, offset, etc.)
 * @iov:    vector with data to write
 * @nr_segs:    number of segments in the vector
 * @ppos:   position where to write
 *
 * This function does all the work needed for actually writing data to a
 * file. It does all basic checks, removes SUID from the file, updates
 * modification times and calls proper subroutines depending on whether we
 * do direct IO or a standard buffered write.
 *
 * It expects i_mutex to be grabbed unless we work on a block device or similar
 * object which does not need locking at all.
 *
 * This function does *not* take care of syncing data in case of O_SYNC write.
 * A caller has to handle it. This is mainly due to the fact that we want to
 * avoid syncing under i_mutex.
 */
ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
                 unsigned long nr_segs, loff_t *ppos)
{
    struct file *file = iocb->ki_filp;
    struct address_space * mapping = file->f_mapping;
    size_t ocount;      /* original count */
    size_t count;       /* after file limit checks */
    struct inode    *inode = mapping->host;
    loff_t      pos;
    ssize_t     written;
    ssize_t     err;

    ocount = 0;
    /*调用generic_segment_checks ()函数确定iovec描述符所描述的用户态缓冲区是有效的,如果参数无效则返回错误*/
    err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
    if (err)
        return err;

    count = ocount;
    pos = *ppos;

    /*将文件file->f_mapping->backing_dev_info的backing_dev_info描述的地址设为current->backing_dev_info。实际上,即使相应请求队列是阻塞的,这个设置也会允许当前进程写回由file->f_mapping拥有的脏页 */
    /* We can write back this queue in page reclaim */
    current->backing_dev_info = mapping->backing_dev_info;
    written = 0;

    /*如果file->flags的O_APPEND标志置位而且文件是普通文件,它将*ppos设为文件尾,从而新数据将都追加到文件的后边*/
    /*对文件的大小进行几次检查*/
    err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
    if (err)
        goto out;

    if (count == 0)
        goto out;

    /*如果设定,则将文件的suid标志清零,而且如果是可执行文件的话就将sgid标志也清零*/
    err = file_remove_suid(file);
    if (err)
        goto out;

    /*将当前时间存放在inode->mtime字段中,而且将索引节点对象标记为脏*/
    err = file_update_time(file);
    if (err)
        goto out;

    /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
    if (unlikely(file->f_flags & O_DIRECT)) {
        loff_t endbyte;
        ssize_t written_buffered;

        written = generic_file_direct_write(iocb, iov, &nr_segs, pos,
                            ppos, count, ocount);
        if (written < 0 || written == count)
            goto out;
        /*
         * direct-io write to a hole: fall through to buffered I/O
         * for completing the rest of the request.
         */
        pos += written;
        count -= written;
        written_buffered = generic_file_buffered_write(iocb, iov,
                        nr_segs, pos, ppos, count,
                        written);
        /*
         * If generic_file_buffered_write() retuned a synchronous error
         * then we want to return the number of bytes which were
         * direct-written, or the error code if that was zero.  Note
         * that this differs from normal direct-io semantics, which
         * will return -EFOO even if some bytes were written.
         */
        if (written_buffered < 0) {
            err = written_buffered;
            goto out;
        }

        /*
         * We need to ensure that the page cache pages are written to
         * disk and invalidated to preserve the expected O_DIRECT
         * semantics.
         */
        endbyte = pos + written_buffered - written - 1;
        err = filemap_write_and_wait_range(file->f_mapping, pos, endbyte);
        if (err == 0) {
            written = written_buffered;
            invalidate_mapping_pages(mapping,
                         pos >> PAGE_CACHE_SHIFT,
                         endbyte >> PAGE_CACHE_SHIFT);
        } else {
            /*
             * We don't know how much we wrote, so just return
             * the number of bytes which were direct-written
             */
        }
    } else {
        written = generic_file_buffered_write(iocb, iov, nr_segs,
                pos, ppos, count, written);
    }
    out:
        current->backing_dev_info = NULL;
        return written ? written : err;
    }

内存映射

一个线性区可以和磁盘文件系统的普通文件的某一部分或者块设备文件相关联,这就意味着内核把对区线性中页内某个字节的访问转换成对文件中相应字节的操作-内存映射

  1. 共享型:在线性区页上的任何写操作都会修改磁盘文件上的文件,而且如果进程对共享映射中的一个页进行写,那么这种修改对于其他映射了这同一文件的所有进程来说都是可见的。
  2. 私有型:当进程创建的映射只是为了读文件,而不是写文件时才会使用此种映射。

进程可以发出一个mmap()系统调用来创建一个新的内存映射。
共享内存的页通常都包含在页高速缓存中,私有内存映射的页只要还没有被修改也都包含在页高速缓存中。当进程试图修改一个私有内存映射的页时,内核就把该页进行复制,并在进程页表中用复制的页来替换原来的页框。虽然原来的页框还仍留在页高速缓存中,但不再属于这个内存映射,这是由于被复制的页框替换了原来的页框。由此,这个复制的页框不会被插入到页高速缓存中,因为其中所包含的数据不在是磁盘上表示文件的那个有效数据。
事实上,一个新建立的内存映射就是一个不包含任何页的线性区。当进程引用线性区中的一个地址时,缺页异常发生,缺页异常中断处理程序检查线性区的nopage方法是否被定义。如果没有定义nopage,则说明线性区不应摄磁盘上的文件;否则,进行映射,这个方法通过访问块设备处理读取的页。
出于效率的原因,内存映射创建之后并没有立即把页框分配给它,而是尽可能向后推迟到不能在推迟,也就是说,当进程试图对其中的一个页进行寻址时,就产生一个“缺页”异常。

把内存映射的脏页刷新到磁盘

进程可以使用msync()系统调用把属于共享内存映射的脏页刷新到磁盘。

非线性内存映射

因为非线性内存映射的内存页是按照相对于文件开始出的页索引存放在页高速缓存中,而不是按照相对于线性区开始处的索引存放的,所以非线性内存映射刷新到磁盘的方式与线性内存映射是一样的。

直接I/O传送

通过绕过页高速缓存的方法直接I/O传送。在每次I/O直接传送中,内核对磁盘控制器进行编程,以便在自缓存的应用程序的用户程序的用户态地址空间中的页与磁盘之间直接传送数据。

异步I/O

标准为异步方式访问定义了一套库函数,“异步”实际上就是:当用户进程调用库函数读写文件时,一旦读写操作进入队列函数就结束,甚至有可能正真的I/O数据传输还没有开始。这样调用进程可以在数据正在传输时继续自己的运行。

文件系统结构图

一下是整理的内核虚拟文件系统以及文件系统数据结构调用关系图:
这里写图片描述
图片显示的不是很清楚,pdf版本的详见链接:文件系统结构图

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第一部分:常用命令 常用命令/文件处理 0:基础功能 1:ls 显示文件目录 语法:ls 选项[-ald][文件或目录] 2:cat 显示文件内容(内容少适合) 语法:cat[文件名] 3:tac 显示文件内容 语法:tac[文件名] 4:more 分页显示文件内容(只能往下翻页,不能往上反) 语法:more[文件名] 5:less 分页显示文件内容(上下翻页) 语法:less[文件名] 6:head 显示文件前面几行 语法:head[文件名] 7:tail 显示文件后面几行 语法:tail[文件名] 8:touch 创建空文件 语法:touch[文件名字] 9:mkdir 创建新目录 语法:mkdir -p 目录 10:cd 切换目录 语法:cd 目录 11:pwd 显示当前目录的绝对路径 语法:pwd 12:rmdir 删除空目录 语法:rmdir 目录名字 13:rm 删除文件或目录 语法:rm -rf[文件或目录] 14:cp 复制文件或目录 语法:cp -rp[源文件或目录][目标目录] 15:scp 远程和本地互传文件 语法:scp [参数] [原路径] [目标路径] 16:mv 剪切文件或该名 语法:mv[源文件或目录][目标目录] 17:ln 生成连接文件 语法:ln -s[原件名][目标文件] 常用命令/文件搜索 1:find 文件搜索 语法:find [搜索范围][比配条件] 2:locate 在文件资料库中查找文件 语法:locate 文件名 3:which 搜索命令所在目录级别名信息 语法:which[命令名称] 4:whereis 搜索命令所在目录级帮助文档路径 语法:whereis[命令名称] 5:grep 在文件中搜索字串匹配的行并输出 语法:grep -iv[指定字串][文件] 6:uname 显示当前操作系统名称 常用命令/压缩解压 1:gzip 压缩文件 语法:gzip [文件] 2:gunzip 解压缩.gz文件 语法:gunzip [压缩文件] 3:tar 打包目录 语法:tar 选项[-zcf][压缩后文件名字][目录] 4:zip 压缩文件或目录 语法:zip 选项[-r][压缩后文件名字][文件或目录] 5:unzip 压缩文件或目录 语法:unzip [压缩文件] 6:bzip2 压缩文件 语法:bzip2 选项[-k][文件] 7:bunzip2 解压缩 语法:bunzip2 选项[-k][解压文件] 常用命令/网络 1:write 给在线用户发消息 语法:write 2:wall 发广播消息 语法:wall [发送的消息] 3:ping 测试网络连通性 语法:ping 选项IP地址 4:ifconfig 查看和设置网卡信息 语法:ifconfig [网卡名称] [IP地址] 5:mail 查看发送电子邮件 语法:mail [用户名] 6:last 列出目前与过去登陆系统的用户信息 语法:last 7:lastlog 检查某用户上次登陆的时间 语法:lastlog 8:traceroute 显示数据包到主机间的路径 语法:traceroute 网址 9:netstat 显示网络相关信息 语法:netstat [-tulrn] 10:setup 配置网络 语法:setup 11:mount 挂载 语法:mount [-t 文件系统] 设备文件名挂载点 12:nmap 端口扫描 13:ifup/ifdown 启动/禁止网卡 常用命令/关机重启 1:shutdown 关机或重启 语法:shutdown [选项] 时间 2:halt 关机 语法:halt 3:poweroff 关机 语法:poweroff 4:init 关机或重启 语法:init [0~6]数字 5:reboot 重启 语法:reboot 6:logout 退出终端 语法:logout 常用命令/帮助 1:man 获得帮助信息 语法:man [命令或配置文件] 2:whatis 获得帮助简短信息 语法:whatis 命令 3:apropos 查看配置文件信息 语法:apropos 配置文件 4:--help 查看命令主要选项 语法:命令 --help 5:info 获取帮助信息 语法:info 命令 6:help 获取Shell内置命令的帮助信息 语法:help 命令 7:apt-get 安装卸载程序 第二部分:文件系统 文件系统/文件系统 0:tree 以树形结构显示文件目录结构 1:分区和文件系统 2:文件系统常用命令 df [选项][挂载点] //统计文件系统占情况 du [选项][目录或文件] //统计目录或文件大小 df和du命令的区别 fsck [选项] 分区设备文件名 //文件系统修复命令 dumpe2fs 分区设备文件名 //显示磁盘状态命令 3:挂载命令 mount [选项] 设备文件名 挂载点 4:挂载光盘与U盘 文件系统/fdisk分区 1:fdisk命令分区过程 2:分区自动挂载与fstab文件修复 文件系统/swap分区 1:free 查看内存与swap分区使用状况 2:创建swap分区或开机自动挂载 第三部分:用户权限 用户权限/用户管理命令 1:useradd 添加新用户 语法:useradd [选项] 用户名 2:passwd 设置用户密码 语法:passwd [选项] 用户名 3:usermod 修改用户信息 语法:usermod [选项] 用户名 4:chage 修改用户密码状态 语法:chage [选项] 用户名 5:userdel 删除用户 语法:userdel [-r] 用户名 6:id 查看用户id 语法:id 用户名 7:su 切换用户身份 语法:su [选项]用户名 8:env 查看用户环境变量 语法:env 9:who 查看登陆用户信息 语法:who 10:w 查看登陆用户详细信息 语法:w 用户权限/用户和用户组管理 1:用户配置文件 1.1:/etc/passwd 用户基本信息文件 1.2:/etc/shadow 影子文件(真正密码,root可以看) 1.3:/etc/group 组信息文件 1.4:/etc/gshadow 密码文件 2:用户管理相关文件 2.1:用户的家目录 2.2:用户的邮箱 /var/spool/mail/用户名/ 2.3:用户模板目录 /etc/skel/ 3:用户管理命令 4:用户组管理命令 第四部分:权限管理 权限管理/权限管理 0:创建用户/添加组 1:chmod 改变文件或目录权限 语法:chmod [{ugoa}{+-=}{rwx}][文件或目录] 2:chown 改变文件或目录所有者 语法:chown [用户][文件或目录] 3:chgrp 改变文件或目录的所属组 语法:chgrp [用户组][文件或目录] 4:umask 显示或设置文件缺省权限 语法:umask[-S] 权限管理/文件特殊权限 1:SetUID 可执行的二进制文件(u:w=s 4) 2:SetGID 可执行的二进制文件或目录(g:r=s 2) 3:Sticky BIT 只对目录有效(o:x=t 1) 权限管理/文件系统属性chattr权限 1:chattr 文件系统属性权限 2:lsattr 查看文件系统属性 权限管理/系统命令sudo权限 1:sudo 权限 权限管理/ACL 权限 1:ACL权限开启 2:查看与设定ACL权限 3:最大有效权限与删除ACL权限 4:默认ACL权限和递归ACL权限 5:删除ACL权限 第五部分:系统管理 系统管理/工作管理 1:把进程放入后台(&,ctrl+z) 2:查看后台的工作 语法:jobs [选项] 3:将后台暂停的工作恢复到前台执行 语法:fg %工作号 4:把后台暂停的工作恢复到后台执行 语法:bg %工作号 系统管理/进程管理 1:进程查看 2:进程管理 2.1:判断服务器健康状态 语法:top [选项] 2.2:查看系统中所有进程 语法:ps [选项] 2.3:查看进程数 语法:pstree [选项] 3:终止进程 3.1:kill [选项] //终止进程 3.1:killall [选项][信号] 进程名 //按照进程名杀死进程 3.1:pkill [选项][信号]进程名 //按照进程名终止进程 系统管理/系统定时任务 1:crond服务管理与访问控制 语法:crontab [选项] 系统管理/系统资源查看 1:vmstat命令监控系统资源 语法: vmstat 刷新延时 刷新次数 2:dmesg开机时内核检测信息 语法: dmesg 3:free查看内存使用状态 语法: free [选项] 4:查看CPU信息 /proc/cpuinfo 5:uptime启动时间和平均负载 语法: uptime 6:uname查看系统与内核相关信息 语法: uname [选项] 7:判断当前系统的位数(32位或64位..) 8:查看当前Linux系统的发行版本 语法: lsb_release -a 9:lsof列出进程打开或使用的文件信息 语法: lsof [选项] 10:date 第六部分:服务管理 1:服务简介与分类 2:RPM包安装服务的管理 2.1:独立服务的管理 2.2:基于xinetd服务的管理 3:源码包安装服务管理 3.1:源码包安装服务的启动 3.2:源码包服务的自启动 3.3:让源码包服务被服务管理器命令识别 第七部分:启动管理 启动管理/CentOS 6.x启动管理 1:系统运行级别 1:运行级别(0~6,7个级别) 2:查看运行级别(runlevel,init) 3:系统默认运行级别(/etc/inittab) 2:系统启动过程 1:initramfs内存文件系统 2:调用/etc/init/rcS.conf配置文件 1:先调用/etc/rc.d/rc.sysinit 2:再调用/etc/inittab确定系统默认运行级别 3:调用/etc/rc.d/rc文件 启动管理/启动引导程序grub 1:grub配置文件 2:grub加密与字符界面分辨率调整 启动管理/系统修复模式 1:单用户模式 2:光盘修复模式 3:Linux的安全性 第八部分:日志管理 日志管理简介 1:日志服务 2:rsyslogd的新特点 3:确定服务启动 4:常见日志的作用(lastb,lastlog,last) 5:其他日志 日志-轮替 1:日志文件的命名规则 2:logrotate配置文件 3:把apache日志加入轮替 4:logrotate日志轮替 语法 logrotate [选项] 配置文件名 rsyslogd-日子服务 1:日志文件格式 2:/etc/rsyslog.comf配置文件 第九部分:软件包管理 软件包管理\软件包管理 1:软件包管理简介 1:源码包(源代码安装包,手动安装) 2:二进制包(RPM包,系统默认包) 2:RPM包管理-rpm命令管理 1:RPM包命名规则 2:RPM包依赖性 3:RPM包管理-yum在线管理 1:IP地址配置和网络yum源 2:光盘yum源搭建 4:源码包管理 1:源码包和RPM包区别 2:源码包安装过程 5:脚本安装包与软件包选择 软件包管理/软件包管理命令 1:RPM包管理 rpm命令管理 命令 1:安装 rpm -ivh 包全名 2:升级 rpm -Uvh 包全名 3:卸载 rpm -e 包名 4:查询 rpm -q.. 5:校验 rpm -V 已安装的包名 6:文件提取 rpm2cpio 包全名 | cpio -idv .文件绝对路径 2:rpm包管理 yum在线管理 命令 1:查询 yum list 2:安装 yum -y install 包名 3:升级 yum -y update 包名 4:卸载 yum -y remove 包名 5:软件组管理 yum grouplist 第十部分:备份与恢复 备份与恢复/备份的概述 1:Linux系统需要备份的数据 2:安装服务的数据 3:备份策略 1:完全备份 2:增量备份 3:差异备份 备份与恢复/dump和restore命令 1:dump备份数据 2:restore恢复命令 第十一部分:shell

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值