一. F2FS文件系统初始化

static int __init init_f2fs_fs(void)
{int err;/* PAGE_SIZE和F2FS_BLKSIZE需要相等, 大小为4096*/if (PAGE_SIZE != F2FS_BLKSIZE) {printk("F2FS not supported on PAGE_SIZE(%lu) != %d\n",PAGE_SIZE, F2FS_BLKSIZE);return -EINVAL;}f2fs_build_trace_ios();/* 初始化f2fs_inode_cache */err = init_inodecache();if (err)goto fail;err = f2fs_create_node_manager_caches();if (err)goto free_inodecache;err = f2fs_create_segment_manager_caches();if (err)goto free_node_manager_caches;err = f2fs_create_checkpoint_caches();if (err)goto free_segment_manager_caches;err = f2fs_create_extent_cache();if (err)goto free_checkpoint_caches;err = f2fs_init_sysfs();if (err)goto free_extent_cache;err = register_shrinker(&f2fs_shrinker_info);if (err)goto free_sysfs;err = register_filesystem(&f2fs_fs_type);if (err)goto free_shrinker;f2fs_create_root_stats();err = f2fs_init_post_read_processing();if (err)goto free_root_stats;return 0;free_root_stats:f2fs_destroy_root_stats();unregister_filesystem(&f2fs_fs_type);
free_shrinker:unregister_shrinker(&f2fs_shrinker_info);
free_sysfs:f2fs_exit_sysfs();
free_extent_cache:f2fs_destroy_extent_cache();
free_checkpoint_caches:f2fs_destroy_checkpoint_caches();
free_segment_manager_caches:f2fs_destroy_segment_manager_caches();
free_node_manager_caches:f2fs_destroy_node_manager_caches();
free_inodecache:destroy_inodecache();
fail:return err;
}

初始化f2fs_inode_cache, 申请f2fs_inode_info内存空间,f2fs_inode_info是描述f2fs inode 信息的结构体

static int __init init_inodecache(void)
{f2fs_inode_cachep = kmem_cache_create("f2fs_inode_cache",sizeof(struct f2fs_inode_info), 0,SLAB_RECLAIM_ACCOUNT|SLAB_ACCOUNT, NULL);if (!f2fs_inode_cachep)return -ENOMEM;return 0;
}struct f2fs_inode_info {struct inode vfs_inode;        /* serve a vfs inode */unsigned long i_flags;       /* keep an inode flags for ioctl */unsigned char i_advise;      /* use to give file attribute hints */unsigned char i_dir_level;    /* use for dentry level for large dir */unsigned int i_current_depth;   /* only for directory depth *//* for gc failure statistic */unsigned int i_gc_failures[MAX_GC_FAILURE];unsigned int i_pino;     /* parent inode number */umode_t i_acl_mode;        /* keep file acl mode temporarily *//* Use below internally in f2fs*/unsigned long flags;       /* use to pass per-file flags */struct rw_semaphore i_sem;  /* protect fi info */atomic_t dirty_pages;      /* # of dirty pages */f2fs_hash_t chash;        /* hash value of given file name */unsigned int clevel;     /* maximum level of given file name */struct task_struct *task; /* lookup and create consistency */struct task_struct *cp_task; /* separate cp/wb IO stats*/nid_t i_xattr_nid;      /* node id that contains xattrs */loff_t    last_disk_size;     /* lastly written file size */#ifdef CONFIG_QUOTAstruct dquot *i_dquot[MAXQUOTAS];/* quota space reservation, managed internally by quota code */qsize_t i_reserved_quota;
#endifstruct list_head dirty_list;  /* dirty list for dirs and files */struct list_head gdirty_list;    /* linked in global dirty list */struct list_head inmem_ilist;  /* list for inmem inodes */struct list_head inmem_pages;    /* inmemory pages managed by f2fs */struct task_struct *inmem_task; /* store inmemory task */struct mutex inmem_lock;   /* lock for inmemory pages */struct extent_tree *extent_tree;   /* cached extent_tree entry *//* avoid racing between foreground op and gc */struct rw_semaphore i_gc_rwsem[2];struct rw_semaphore i_mmap_sem;struct rw_semaphore i_xattr_sem; /* avoid racing between reading and changing EAs */int i_extra_isize;        /* size of extra space located in i_addr */kprojid_t i_projid;      /* id for project quota */int i_inline_xattr_size;  /* inline xattr size */struct timespec64 i_crtime;  /* inode creation time */struct timespec64 i_disk_time[4];/* inode disk times */
};

申请f2fs node 管理相关的slab 内存空间,描述 node管理信息相关的结构体是 nat_entry, free_nid, nat_entry_set, fsync_node_entry.

int __init f2fs_create_node_manager_caches(void)
{nat_entry_slab = f2fs_kmem_cache_create("nat_entry",sizeof(struct nat_entry));if (!nat_entry_slab)goto fail;free_nid_slab = f2fs_kmem_cache_create("free_nid",sizeof(struct free_nid));if (!free_nid_slab)goto destroy_nat_entry;nat_entry_set_slab = f2fs_kmem_cache_create("nat_entry_set",sizeof(struct nat_entry_set));if (!nat_entry_set_slab)goto destroy_free_nid;fsync_node_entry_slab = f2fs_kmem_cache_create("fsync_node_entry",sizeof(struct fsync_node_entry));if (!fsync_node_entry_slab)goto destroy_nat_entry_set;return 0;destroy_nat_entry_set:kmem_cache_destroy(nat_entry_set_slab);
destroy_free_nid:kmem_cache_destroy(free_nid_slab);
destroy_nat_entry:kmem_cache_destroy(nat_entry_slab);
fail:return -ENOMEM;
}struct nat_entry {struct list_head list;   /* for clean or dirty nat list */struct node_info ni;   /* in-memory node information */
};/** For node information*/
struct node_info {nid_t nid;        /* node id */nid_t ino;     /* inode number of the node's owner */block_t  blk_addr;   /* block address of the node */unsigned char version;   /* version of the node */unsigned char flag;    /* for node information bits */
};struct free_nid {struct list_head list;   /* for free node id list */nid_t nid;       /* node id */int state;     /* in use or not: FREE_NID or PREALLOC_NID */
};struct nat_entry_set {struct list_head set_list;  /* link with other nat sets */struct list_head entry_list;  /* link with dirty nat entries */nid_t set;         /* set number*/unsigned int entry_cnt;      /* the # of nat entries in set */
};struct fsync_node_entry {struct list_head list;   /* list head */struct page *page;   /* warm node page pointer */unsigned int seq_id;    /* sequence id */
};

申请f2fs segment管理相关的slab 内存空间,描述segment管理信息相关的结构体是 discard_entry, discard_cmd, sit_entry_set, inmem_pages.

int __init f2fs_create_segment_manager_caches(void)
{discard_entry_slab = f2fs_kmem_cache_create("discard_entry",sizeof(struct discard_entry));if (!discard_entry_slab)goto fail;discard_cmd_slab = f2fs_kmem_cache_create("discard_cmd",sizeof(struct discard_cmd));if (!discard_cmd_slab)goto destroy_discard_entry;sit_entry_set_slab = f2fs_kmem_cache_create("sit_entry_set",sizeof(struct sit_entry_set));if (!sit_entry_set_slab)goto destroy_discard_cmd;inmem_entry_slab = f2fs_kmem_cache_create("inmem_page_entry",sizeof(struct inmem_pages));if (!inmem_entry_slab)goto destroy_sit_entry_set;return 0;destroy_sit_entry_set:kmem_cache_destroy(sit_entry_set_slab);
destroy_discard_cmd:kmem_cache_destroy(discard_cmd_slab);
destroy_discard_entry:kmem_cache_destroy(discard_entry_slab);
fail:return -ENOMEM;
}/* for the bitmap indicate blocks to be discarded */
struct discard_entry {struct list_head list;    /* list head */block_t start_blkaddr;   /* start blockaddr of current segment */unsigned char discard_map[SIT_VBLOCK_MAP_SIZE]; /* segment discard bitmap */
};struct discard_cmd {struct rb_node rb_node;       /* rb node located in rb-tree */union {struct {block_t lstart;  /* logical start address */block_t len; /* length */block_t start;  /* actual start address in dev */};struct discard_info di;  /* discard info */};struct list_head list;      /* command list */struct completion wait;       /* compleation */struct block_device *bdev; /* bdev */unsigned short ref;       /* reference count */unsigned char state;       /* state */unsigned char queued;        /* queued discard */int error;          /* bio error */spinlock_t lock;     /* for state/bio_ref updating */unsigned short bio_ref;     /* bio reference count */
};struct sit_entry_set {struct list_head set_list;  /* link with all sit sets */unsigned int start_segno;   /* start segno of sits in set */unsigned int entry_cnt;     /* the # of sit entries in set */
};struct sit_entry_set {struct list_head set_list;  /* link with all sit sets */unsigned int start_segno;   /* start segno of sits in set */unsigned int entry_cnt;     /* the # of sit entries in set */
};

申请f2fs checkpoint管理相关的slab 内存空间,描述checkpoint管理信息相关的结构体是.inode_entry

int __init f2fs_create_checkpoint_caches(void)
{ino_entry_slab = f2fs_kmem_cache_create("f2fs_ino_entry",sizeof(struct ino_entry));if (!ino_entry_slab)return -ENOMEM;f2fs_inode_entry_slab = f2fs_kmem_cache_create("f2fs_inode_entry",sizeof(struct inode_entry));if (!f2fs_inode_entry_slab) {kmem_cache_destroy(ino_entry_slab);return -ENOMEM;}return 0;
}/* for the list of inodes to be GCed */
struct inode_entry {struct list_head list;  /* list head */struct inode *inode; /* vfs inode pointer */
};

创建f2fs extent cache内存空间

int __init f2fs_create_extent_cache(void)
{extent_tree_slab = f2fs_kmem_cache_create("f2fs_extent_tree",sizeof(struct extent_tree));if (!extent_tree_slab)return -ENOMEM;extent_node_slab = f2fs_kmem_cache_create("f2fs_extent_node",sizeof(struct extent_node));if (!extent_node_slab) {kmem_cache_destroy(extent_tree_slab);return -ENOMEM;}return 0;
}struct extent_info {unsigned int fofs;     /* start offset in a file */unsigned int len;       /* length of the extent */u32 blk;          /* start block address of the extent */
};struct extent_node {struct rb_node rb_node;       /* rb node located in rb-tree */struct extent_info ei;      /* extent info */struct list_head list;     /* node in global extent list of sbi */struct extent_tree *et;      /* extent tree pointer */
};struct extent_tree {nid_t ino;            /* inode number */struct rb_root_cached root;   /* root of extent info rb-tree */struct extent_node *cached_en; /* recently accessed extent node */struct extent_info largest;  /* largested extent info */struct list_head list;       /* to be used by sbi->zombie_list */rwlock_t lock;           /* protect extent info rb-tree */atomic_t node_cnt;     /* # of extent node in rb-tree*/bool largest_updated;       /* largest extent updated */
};

创建sys/fs/f2fs目录

int __init f2fs_init_sysfs(void)
{int ret;kobject_set_name(&f2fs_kset.kobj, "f2fs");f2fs_kset.kobj.parent = fs_kobj;ret = kset_register(&f2fs_kset);if (ret)return ret;ret = kobject_init_and_add(&f2fs_feat, &f2fs_feat_ktype,NULL, "features");if (ret)kset_unregister(&f2fs_kset);elsef2fs_proc_root = proc_mkdir("fs/f2fs", NULL);return ret;
}

注册f2fs_shrinker_info信息

int register_shrinker(struct shrinker *shrinker)
{int err = prealloc_shrinker(shrinker);if (err)return err;register_shrinker_prepared(shrinker);return 0;
}/* f2fs-wide shrinker description */
static struct shrinker f2fs_shrinker_info = {.scan_objects = f2fs_shrink_scan,.count_objects = f2fs_shrink_count,.seeks = DEFAULT_SEEKS,
};

注册f2fs文件系统


/***    register_filesystem - register a new filesystem*    @fs: the file system structure**   Adds the file system passed to the list of file systems the kernel* is aware of for mount and other syscalls. Returns 0 on success,*    or a negative errno code on an error.** The &struct file_system_type that is passed is linked into the kernel * structures and must not be freed until the file system has been*    unregistered.*/int register_filesystem(struct file_system_type * fs)
{int res = 0;struct file_system_type ** p;BUG_ON(strchr(fs->name, '.'));if (fs->next)return -EBUSY;write_lock(&file_systems_lock);p = find_filesystem(fs->name, strlen(fs->name));if (*p)res = -EBUSY;else*p = fs;write_unlock(&file_systems_lock);return res;
}static struct file_system_type f2fs_fs_type = {.owner     = THIS_MODULE,.name        = "f2fs",.mount      = f2fs_mount,.kill_sb  = kill_f2fs_super,.fs_flags    = FS_REQUIRES_DEV,
};
MODULE_ALIAS_FS("f2fs");

f2fs create root tats

void __init f2fs_create_root_stats(void)
{f2fs_debugfs_root = debugfs_create_dir("f2fs", NULL);debugfs_create_file("status", S_IRUGO, f2fs_debugfs_root, NULL,&stat_fops);
}/* DEFINE_SHOW_ATTRIBUTE是将 __name ## _open和__name ## _fops封装之后的宏,达到简化的效果,
我们只需要去实现 __name ## _show(这里是指的是stat_show函数),当用户读取status文件时,会直接调用__name ## _show函数(即调用stat_show函数)
DEFINE_SHOW_ATTRIBUTE(stat);#define DEFINE_SHOW_ATTRIBUTE(__name)                   \
static int __name ## _open(struct inode *inode, struct file *file)  \
{                                   \return single_open(file, __name ## _show, inode->i_private);    \
}                                   \\
static const struct file_operations __name ## _fops = {            \.owner     = THIS_MODULE,                 \.open      = __name ## _open,             \.read      = seq_read,                    \.llseek        = seq_lseek,                   \.release   = single_release,              \
}static void *single_start(struct seq_file *p, loff_t *pos)
{return NULL + (*pos == 0);
}static void *single_next(struct seq_file *p, void *v, loff_t *pos)
{++*pos;return NULL;
}static void single_stop(struct seq_file *p, void *v)
{
}int single_open(struct file *file, int (*show)(struct seq_file *, void *),void *data)
{struct seq_operations *op = kmalloc(sizeof(*op), GFP_KERNEL_ACCOUNT);int res = -ENOMEM;if (op) {op->start = single_start;op->next = single_next;op->stop = single_stop;op->show = show;res = seq_open(file, op);if (!res)((struct seq_file *)file->private_data)->private = data;elsekfree(op);}return res;
}
EXPORT_SYMBOL(single_open);static int stat_show(struct seq_file *s, void *v)
{struct f2fs_stat_info *si;int i = 0;int j;mutex_lock(&f2fs_stat_mutex);list_for_each_entry(si, &f2fs_stat_list, stat_list) {update_general_status(si->sbi);seq_printf(s, "\n=====[ partition info(%pg). #%d, %s, CP: %s]=====\n",si->sbi->sb->s_bdev, i++,f2fs_readonly(si->sbi->sb) ? "RO": "RW",is_set_ckpt_flags(si->sbi, CP_DISABLED_FLAG) ?"Disabled": (f2fs_cp_error(si->sbi) ? "Error": "Good"));seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ",si->sit_area_segs, si->nat_area_segs);seq_printf(s, "[SSA: %d] [MAIN: %d",si->ssa_area_segs, si->main_area_segs);seq_printf(s, "(OverProv:%d Resv:%d)]\n\n",si->overp_segs, si->rsvd_segs);if (test_opt(si->sbi, DISCARD))seq_printf(s, "Utilization: %u%% (%u valid blocks, %u discard blocks)\n",si->utilization, si->valid_count, si->discard_blks);elseseq_printf(s, "Utilization: %u%% (%u valid blocks)\n",si->utilization, si->valid_count);seq_printf(s, "  - Node: %u (Inode: %u, ",si->valid_node_count, si->valid_inode_count);seq_printf(s, "Other: %u)\n  - Data: %u\n",si->valid_node_count - si->valid_inode_count,si->valid_count - si->valid_node_count);seq_printf(s, "  - Inline_xattr Inode: %u\n",si->inline_xattr);seq_printf(s, "  - Inline_data Inode: %u\n",si->inline_inode);seq_printf(s, "  - Inline_dentry Inode: %u\n",si->inline_dir);seq_printf(s, "  - Orphan/Append/Update Inode: %u, %u, %u\n",si->orphans, si->append, si->update);seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n",si->main_area_segs, si->main_area_sections,si->main_area_zones);seq_printf(s, "  - COLD  data: %d, %d, %d\n",si->curseg[CURSEG_COLD_DATA],si->cursec[CURSEG_COLD_DATA],si->curzone[CURSEG_COLD_DATA]);seq_printf(s, "  - WARM  data: %d, %d, %d\n",si->curseg[CURSEG_WARM_DATA],si->cursec[CURSEG_WARM_DATA],si->curzone[CURSEG_WARM_DATA]);seq_printf(s, "  - HOT   data: %d, %d, %d\n",si->curseg[CURSEG_HOT_DATA],si->cursec[CURSEG_HOT_DATA],si->curzone[CURSEG_HOT_DATA]);seq_printf(s, "  - Dir   dnode: %d, %d, %d\n",si->curseg[CURSEG_HOT_NODE],si->cursec[CURSEG_HOT_NODE],si->curzone[CURSEG_HOT_NODE]);seq_printf(s, "  - File   dnode: %d, %d, %d\n",si->curseg[CURSEG_WARM_NODE],si->cursec[CURSEG_WARM_NODE],si->curzone[CURSEG_WARM_NODE]);seq_printf(s, "  - Indir nodes: %d, %d, %d\n",si->curseg[CURSEG_COLD_NODE],si->cursec[CURSEG_COLD_NODE],si->curzone[CURSEG_COLD_NODE]);seq_printf(s, "\n  - Valid: %d\n  - Dirty: %d\n",si->main_area_segs - si->dirty_count -si->prefree_count - si->free_segs,si->dirty_count);seq_printf(s, "  - Prefree: %d\n  - Free: %d (%d)\n\n",si->prefree_count, si->free_segs, si->free_secs);seq_printf(s, "CP calls: %d (BG: %d)\n",si->cp_count, si->bg_cp_count);seq_printf(s, "  - cp blocks : %u\n", si->meta_count[META_CP]);seq_printf(s, "  - sit blocks : %u\n",si->meta_count[META_SIT]);seq_printf(s, "  - nat blocks : %u\n",si->meta_count[META_NAT]);seq_printf(s, "  - ssa blocks : %u\n",si->meta_count[META_SSA]);seq_printf(s, "GC calls: %d (BG: %d)\n",si->call_count, si->bg_gc);seq_printf(s, "  - data segments : %d (%d)\n",si->data_segs, si->bg_data_segs);seq_printf(s, "  - node segments : %d (%d)\n",si->node_segs, si->bg_node_segs);seq_printf(s, "Try to move %d blocks (BG: %d)\n", si->tot_blks,si->bg_data_blks + si->bg_node_blks);seq_printf(s, "  - data blocks : %d (%d)\n", si->data_blks,si->bg_data_blks);seq_printf(s, "  - node blocks : %d (%d)\n", si->node_blks,si->bg_node_blks);seq_printf(s, "Skipped : atomic write %llu (%llu)\n",si->skipped_atomic_files[BG_GC] +si->skipped_atomic_files[FG_GC],si->skipped_atomic_files[BG_GC]);seq_printf(s, "BG skip : IO: %u, Other: %u\n",si->io_skip_bggc, si->other_skip_bggc);seq_puts(s, "\nExtent Cache:\n");seq_printf(s, "  - Hit Count: L1-1:%llu L1-2:%llu L2:%llu\n",si->hit_largest, si->hit_cached,si->hit_rbtree);seq_printf(s, "  - Hit Ratio: %llu%% (%llu / %llu)\n",!si->total_ext ? 0 :div64_u64(si->hit_total * 100, si->total_ext),si->hit_total, si->total_ext);seq_printf(s, "  - Inner Struct Count: tree: %d(%d), node: %d\n",si->ext_tree, si->zombie_tree, si->ext_node);seq_puts(s, "\nBalancing F2FS Async:\n");seq_printf(s, "  - DIO (R: %4d, W: %4d)\n",si->nr_dio_read, si->nr_dio_write);seq_printf(s, "  - IO_R (Data: %4d, Node: %4d, Meta: %4d\n",si->nr_rd_data, si->nr_rd_node, si->nr_rd_meta);seq_printf(s, "  - IO_W (CP: %4d, Data: %4d, Flush: (%4d %4d %4d), ""Discard: (%4d %4d)) cmd: %4d undiscard:%4u\n",si->nr_wb_cp_data, si->nr_wb_data,si->nr_flushing, si->nr_flushed,si->flush_list_empty,si->nr_discarding, si->nr_discarded,si->nr_discard_cmd, si->undiscard_blks);seq_printf(s, "  - inmem: %4d, atomic IO: %4d (Max. %4d), ""volatile IO: %4d (Max. %4d)\n",si->inmem_pages, si->aw_cnt, si->max_aw_cnt,si->vw_cnt, si->max_vw_cnt);seq_printf(s, "  - nodes: %4d in %4d\n",si->ndirty_node, si->node_pages);seq_printf(s, "  - dents: %4d in dirs:%4d (%4d)\n",si->ndirty_dent, si->ndirty_dirs, si->ndirty_all);seq_printf(s, "  - datas: %4d in files:%4d\n",si->ndirty_data, si->ndirty_files);seq_printf(s, "  - quota datas: %4d in quota files:%4d\n",si->ndirty_qdata, si->nquota_files);seq_printf(s, "  - meta: %4d in %4d\n",si->ndirty_meta, si->meta_pages);seq_printf(s, "  - imeta: %4d\n",si->ndirty_imeta);seq_printf(s, "  - NATs: %9d/%9d\n  - SITs: %9d/%9d\n",si->dirty_nats, si->nats, si->dirty_sits, si->sits);seq_printf(s, "  - free_nids: %9d/%9d\n  - alloc_nids: %9d\n",si->free_nids, si->avail_nids, si->alloc_nids);seq_puts(s, "\nDistribution of User Blocks:");seq_puts(s, " [ valid | invalid | free ]\n");seq_puts(s, "  [");for (j = 0; j < si->util_valid; j++)seq_putc(s, '-');seq_putc(s, '|');for (j = 0; j < si->util_invalid; j++)seq_putc(s, '-');seq_putc(s, '|');for (j = 0; j < si->util_free; j++)seq_putc(s, '-');seq_puts(s, "]\n\n");seq_printf(s, "IPU: %u blocks\n", si->inplace_count);seq_printf(s, "SSR: %u blocks in %u segments\n",si->block_count[SSR], si->segment_count[SSR]);seq_printf(s, "LFS: %u blocks in %u segments\n",si->block_count[LFS], si->segment_count[LFS]);/* segment usage info */update_sit_info(si->sbi);seq_printf(s, "\nBDF: %u, avg. vblocks: %u\n",si->bimodal, si->avg_vblocks);/* memory footprint */update_mem_info(si->sbi);seq_printf(s, "\nMemory: %llu KB\n",(si->base_mem + si->cache_mem + si->page_mem) >> 10);seq_printf(s, "  - static: %llu KB\n",si->base_mem >> 10);seq_printf(s, "  - cached: %llu KB\n",si->cache_mem >> 10);seq_printf(s, "  - paged : %llu KB\n",si->page_mem >> 10);}mutex_unlock(&f2fs_stat_mutex);return 0;
}

初始化f2fs post read processing

int __init f2fs_init_post_read_processing(void)
{bio_post_read_ctx_cache = KMEM_CACHE(bio_post_read_ctx, 0);if (!bio_post_read_ctx_cache)goto fail;bio_post_read_ctx_pool =mempool_create_slab_pool(NUM_PREALLOC_POST_READ_CTXS,bio_post_read_ctx_cache);if (!bio_post_read_ctx_pool)goto fail_free_cache;return 0;fail_free_cache:kmem_cache_destroy(bio_post_read_ctx_cache);
fail:return -ENOMEM;
}struct bio_post_read_ctx {struct bio *bio;struct work_struct work;unsigned int cur_step;unsigned int enabled_steps;
};

f2fs学习三: 文件系统初始化相关推荐

  1. f2fs学习笔记 - 6. f2fs初始化流程

    1.前言 初始流程主要包含f2fs文件系统初始化,以及f2fs文件系统mount 2. init_f2fs_fs init_inodecache 创建f2fs_inode_cache slab描述符 ...

  2. Docker学习三:Docker 数据管理

    前言 本次学习来自于datawhale组队学习: 教程地址为: https://github.com/datawhalechina/team-learning-program/tree/master/ ...

  3. 转自IBM学习 浅析 Linux 初始化 init 系统,第 3 部分 Systemd

    Systemd 的简介和特点 原文链接  https://www.ibm.com/developerworks/cn/linux/1407_liuming_init3/index.html?ca=dr ...

  4. C#多线程学习(三) 生产者和消费者

    C#多线程学习(三) 生产者和消费者 原文链接:http://kb.cnblogs.com/page/42530/ 本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操 ...

  5. 深度学习三(PyTorch物体检测实战)

    深度学习三(PyTorch物体检测实战) 文章目录 深度学习三(PyTorch物体检测实战) 1.网络骨架:Backbone 1.1.神经网络基本组成 1.1.1.卷积层 1.1.2.激活函数层 1. ...

  6. linux文件系统初始化过程(6)---执行init程序

    一.目的 内核加载完initrd文件后,为挂载磁盘文件系统做好了必要的准备工作,包括挂载了sysfs.proc文件系统,加载了磁盘驱动程序驱动程序等.接下来,内核跳转到用户空间的init程序,由ini ...

  7. 深度学习三巨头共获 2018 年图灵奖(经典重温)!

    整理 | 琥珀 出品 | AI科技大本营(ID:rgznai100) 2019 年 3 月 27 日,ACM 宣布,深度学习三位大牛 Yoshua Bengio.Yann LeCun.Geoffrey ...

  8. C#多线程学习(三) 生产者和消费者 (转载系列)——继续搜索引擎研究

    前面说过,每个线程都有自己的资源,但是代码区是共享的,即每个线程都可以执行相同的函数.这可能带来的问题就是几个线程同时执行一个函数,导致数据的混乱,产生不可预料的结果,因此我们必须避免这种情况的发生. ...

  9. GitHub快速学习-三

    title: GitHub快速学习(三) categories: GitHub tags: github abbrlink: 1065435774 date: 2019-06-27 14:34:28 ...

最新文章

  1. unity 纹理压缩格式‘_[2018.1]Unity贴图压缩格式设置
  2. 使用Git向GitHub上传代码
  3. FileChannel与ByteBuffer的使用示例
  4. 关机时无人照管更新正在运行_路辉物流设备:无人化分拣作业驱动物流业降本增效...
  5. SSH报错:packet_write_wait: Connection to xxx Broken pipe 解决
  6. 【项目实战】基于 springboot + mybatis + mysql 的电脑商城项目(附源码)
  7. 如何在服务器上上传手游源码,【仙变3手游】跨服服务端游戏源码+架设教程+双端+后台...
  8. 基于PHP+小程序(MINA框架)+Mysql数据库的汽车维修保养小程序系统设计与实现
  9. 微信HOOK-微信逆向-微信公众号爬虫系统
  10. 单词记忆 词根词缀记忆 总结
  11. ONLYOFFICE 如何连接集成到 Wordpress 上
  12. 英语不规则动词变化时态变化表
  13. android xml画斜线,API返回XML引号通过反斜线
  14. 如何一次性查询千百个顺丰快递的详细物流信息
  15. linux下DNS配置及域名解析服务,linux DNS域名解析服务
  16. 从《我要投资》,看藏在“对立面”里的创业正解
  17. hd530黑苹果硬解_解决黑苹果HD3000核显 VGA和HDMI外接显示器无反应问题
  18. 戴尔计算机主机型号,戴尔电脑在哪看型号_戴尔电脑型号怎么看
  19. LIS2MDL磁力计驱动
  20. 案例精选 | 志翔科技:安全与高效并重 构筑芯片行业数据安全堡垒

热门文章

  1. 读书笔记-别说你懂写网文
  2. C. Anu Has a Function(位运算思维)
  3. HTML瀑布流布局——世界名胜古迹(含图片)
  4. java输出画一个爱心
  5. uniapp开发App引导页
  6. 关于主机的思维导图_送给孩子最好的思维导图课程
  7. 矩阵论 内积空间几何表示图解
  8. 小米(绿米联创)39元 无线开关破解(NXP JN5169 zigbee 3.0开发实战)
  9. 解决winscp中普通用户无法上传、删除、移动文件
  10. 如何查询PC端的蓝牙Bluetooth版本