当前位置: 首页 > news >正文

现在什么视频网站做的最好可以做外贸私单的网站

现在什么视频网站做的最好,可以做外贸私单的网站,wordpress上传音乐播放器,环球资源网怎么找客户目录前言内核对进程和线程的表示创建进程的过程创建线程的过程创建进程和线程的异同揭秘 do_fork 系统调用结论前言 昨天面试的时候#xff0c;面试官问我了个平平淡淡的问题–“聊聊Linux中进程和线程”; 相比大家不管是在考试还是面试中或多或少都遇到过这个问题… 目录前言内核对进程和线程的表示创建进程的过程创建线程的过程创建进程和线程的异同揭秘 do_fork 系统调用结论前言 昨天面试的时候面试官问我了个平平淡淡的问题–“聊聊Linux中进程和线程”; 相比大家不管是在考试还是面试中或多或少都遇到过这个问题俗话说得好: 进程是资源分配的基本单位线程是资源调度的基本单位 这个你我都知道但是这样解释感觉有点牵强和敷衍记住八股不是背的是要理解这样面试才能有深度配合上清晰的逻辑表达凡可百战百胜 在网上对进程和线程的讨论中很多都是聚集在这二位有啥不同。但事实在 Linux 上进程和线程的相同点要远远大于不同点。在 Linux 下的线程甚至都被称为了轻量级进程。(至于说轻量在哪儿稍后我们最终结论就会浮现) 我今天就给大家从 Linux 内核实现的角度给大家深度对比下进程和线程。 内核对进程和线程的表示 都用task_struct表示 对于线程来讲所有的task_struct字段都是和进程一样的本来就是一个结构体来表示的。包括状态、pid、task 树关系、地址空间、文件系统信息、打开的文件信息等等字段线程也都有。 对于进程来说这个 pid 就是我们平时常说的进程 pid。 对于线程来说我们假如一个进程下创建了多个线程出来。那么每个线程的 pid 都是不同的。但是我们一般又需要记录线程是属于哪个进程的。这时候tgid 就派上用场了通过 tgid 字段来表示自己所归属的进程 ID 这样内核通过 tgid 可以知道线程属于哪个进程。 这也就是我前面说的进程和线程的相同点要远远大于不同点本质上是同一个东西都是一个 task_struct 正因为进程线程如此之相像所以在 Linux 下的线程还有另外一个名字叫轻量级进程。(至于说轻量在哪儿稍后我们最终结论就会浮现) 创建进程的过程 Linux下每个进程本质上是一个task_structPCB这点可以参考我的这篇文章Linux虚拟地址空间 事实上进程线程创建的时候使用的函数看起来不一样。但实际在底层实现上最终都是使用同一个函数来实现的: 通过分析内核源码创建进程时fork 调用主要就是执行了 do_fork 函数。 注意fork 函数调用 do_fork 的传的参数分别是SIGCHLD、0,0,NULL,NULL //file:kernel/fork.c SYSCALL_DEFINE0(fork) {return do_fork(SIGCHLD, 0, 0, NULL, NULL); do_fork() 函数又调用 copy_process 完成进程的创建。 //file:kernel/fork.c long do_fork(...) {//复制一个 task_struct 出来struct task_struct *p;p copy_process(clone_flags, ...);... }copy_process()系统调用源码放下下面线程的最终介绍方便区分创建进程和创建线程本质的区别 创建线程的过程 同样如上图: 通过分析源码,lib库中的pthread_create创建线程会调用**clone()**系统调用,为其传入了一组 flag。 //file:nptl/sysdeps/pthread/createthread.c static int create_thread (struct pthread *pd, ...) {int clone_flags (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL| CLONE_SETTLS | CLONE_PARENT_SETTID| CLONE_CHILD_CLEARTID | CLONE_SYSVSEM| 0); //这个flag传入了下面的do_clone()int res do_clone (pd, attr, clone_flags, ...);... }do_clone()会执行一段汇编代码进入clone系统调用: //file:sysdeps/unix/sysv/linux/i386/clone.S ENTRY (BP_SYM (__clone))...movl $SYS_ify(clone),%eax...紧接着查看系统调用clone()的实现发现调用了do_fork() //file:kernel/fork.c SYSCALL_DEFINE5(clone, ......) {return do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr); }验证了上图还是执行到了内核中的do_fork() 函数,下面是do_fork()的源码: //file:kernel/fork.c long do_fork(unsigned long clone_flags, ...) {//复制一个 task_struct 出来struct task_struct *p;p copy_process(clone_flags, stack_start, stack_size,child_tidptr, NULL, trace);//子任务加入到就绪队列中去等待调度器调度wake_up_new_task(p);... }验证了上图do_fork() 函数进一步执行了copy_process()系统调用上源码: //file:kernel/fork.c static struct task_struct *copy_process(...) {//4.1 复制进程 task_struct 结构体struct task_struct *p;p dup_task_struct(current);...//4.2 拷贝 files_structretval copy_files(clone_flags, p);//4.3 拷贝 fs_structretval copy_fs(clone_flags, p);//4.4 拷贝 mm_structretval copy_mm(clone_flags, p);//4.5 拷贝进程的命名空间 nsproxyretval copy_namespaces(clone_flags, p);//4.6 申请 pid 设置进程号pid alloc_pid(p-nsproxy-pid_ns);p-pid pid_nr(pid);p-tgid p-pid;if (clone_flags CLONE_THREAD)p-tgid current-tgid;...... }可以看到copy_process先copy了task_struct然后紧接着有许多对task_struct中一些字段的拷贝函数这些拷贝函数的处理规则取决于clone传入的参数clone_flags这也是进程线程最本质的区别下面进行总结 创建进程和线程的异同 可见和创建进程时使用的 fork 系统调用相比创建线程的 clone 系统调用几乎和 fork 差不多也一样使用的是内核里的 do_fork 函数最后走到 copy_process 来完整创建。 不过创建过程的区别是二者在调用 do_fork 时传入的 clone_flags 里的标记不一样。 创建进程时的 flag仅有一个 SIGCHLD创建线程时的 flag包括 CLONE_VM、CLONE_FS、CLONE_FILES、CLONE_SIGNAL、CLONE_SETTLS、CLONE_PARENT_SETTID、CLONE_CHILD_CLEARTID、CLONE_SYSVSEM。 关于线程多传入的这些 flag 的含义我们选几个关键的做一个简单的介绍: CLONE_VM: 新 task 和父进程共享地址空间CLONE_FS新 task 和父进程共享文件系统信息CLONE_FILES新 task 和父进程共享文件描述符表 这些 flag 会对 task_struct 产生啥影响我们接着看接下来的内容 揭秘 do_fork 系统调用 前面我们看到进程和线程创建都是调用内核中的 do_fork 函数来执行的。在 do_fork 的实现中核心是一个 copy_process 函数它以拷贝父进程线程的方式来生成一个新的 task_struct 出来。 //file:kernel/fork.c long do_fork(unsigned long clone_flags, ...) {//复制一个 task_struct 出来struct task_struct *p;p copy_process(clone_flags, stack_start, stack_size,child_tidptr, NULL, trace);//子任务加入到就绪队列中去等待调度器调度wake_up_new_task(p);... }在创建完毕后调用 wake_up_new_task 将新创建的任务添加到就绪队列中等待调度器调度执行。这个代码很长我对其进行了一定程度的精简 //file:kernel/fork.c static struct task_struct *copy_process(...) {//4.1 复制进程 task_struct 结构体struct task_struct *p;p dup_task_struct(current);...//4.2 拷贝 files_structretval copy_files(clone_flags, p);//4.3 拷贝 fs_structretval copy_fs(clone_flags, p);//4.4 拷贝 mm_structretval copy_mm(clone_flags, p);//4.5 拷贝进程的命名空间 nsproxyretval copy_namespaces(clone_flags, p);//4.6 申请 pid 设置进程号pid alloc_pid(p-nsproxy-pid_ns);p-pid pid_nr(pid);p-tgid p-pid;if (clone_flags CLONE_THREAD)p-tgid current-tgid;...... }可见copy_process 先是复制了一个新的 task_struct 出来然后调用 copy_xxx 系列的函数对 task_struct 中的各种核心字段进行拷贝处理还申请了 新的pid 。 copy task_struct中各种字段时候的处理方式就是区分进程和线程的重点 创建进程中因为没有传入task_struct中那些共享的字段则他们都多copy了一份有自己的内存空间注意存在写时拷贝) 通过mm_struct字段访问物理内存的过程: 创建线程时,因为传入了task_struct中各种字段的共享标志位则对应task_struct的各字段是共享的 通过mm_struct字段访问物理内存的过程: 结论 对于进程来讲地址空间 mm_struct、挂载点 fs_struct、打开文件列表 files_struct 等各种task_struct中的核心字段都要是独立拥有的都需要去申请新的内存并初始化它们。这也体现了进程之间字段不共享资源分配的基本单位 对于线程来讲其地址空间 mm_struct、目录信息 fs_struct、打开文件列表 files_struct 等各种task_struct中的核心字段都是和创建它的任务共享的;这也体现了线程和创建他的进程字段等资源共享但线程有唯一pid是调度的基本单位 总之在 Linux 内核中并没有对线程做特殊处理还是由 task_struct 来管理。从内核的角度看用户态的线程本质上还是一个进程。只不过和普通进程比稍微“轻量”了那么一些(轻量在共享了各字段)
http://www.w-s-a.com/news/23213/

相关文章:

  • 注册功能的网站怎么做做网站容易还是编程容易
  • wordpress建立目录seo编辑培训
  • 网站怎么群发广州现在可以正常出入吗
  • 微信有网站开发吗多语种网站
  • 深圳网站设计 建设首选深圳市室内设计公司排名前50
  • 上海网站建设 觉策动力wordpress接口开发
  • 网站建设服务器的选择方案小型视频网站建设
  • 江宁做网站价格扬州立扬计算机培训网站建设怎么样
  • 手表网站背景开发新客户的十大渠道
  • 定制网站设计wordpress写的网站
  • p2p网站建设公司排名成都装饰公司
  • 网站被k怎么恢复wordpress缓存类
  • 做外贸有哪些网站平台最近文章 wordpress
  • joomla网站模板一个人做网站的swot
  • 南京建设网站需要多少钱深圳专业网站建设制作价格
  • 天河建网站装修公司线上推广方式
  • 超市网站怎么做的目前最流行的拓客方法
  • 做文字logo的网站贵阳商城网站开发
  • 沧州有没有做网站的中国建筑设计
  • 建设网站 系统占用空间在线代理浏览网站
  • 做海报有什么参考的网站网站建设验收合同
  • 酒店网站制作wordpress文章评论设置
  • 造一个官方网站wordpress mysql类
  • 怎么做卡商网站河南做网站找谁
  • 网站建设招标方案模板上线啦 图谱智能网站
  • 龙口网站建设公司哪家好wordpress 上传类型
  • 做外贸主要看什么网站服务平台的宗旨
  • 宜昌营销型网站购买网站
  • 如何查询网站建设时间wordpress 框架解析
  • 网站建设年终总结网站建设公司顺义