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

沈阳军成网站建设江苏建设监理网站

沈阳军成网站建设,江苏建设监理网站,南宁百度seo放心选择,网站建设成本费用前言#xff1a;本章我们主要讲解进程的创建与终止#xff0c;最后简单介绍一下 slab 分派器。 一、进程创建#xff08;Process creation#xff09; 1、分叉函数 fork 在 中#xff0c; fork 函数是非常重要的函数#xff0c;它从已存在进程中创建一个新的进程。 …前言本章我们主要讲解进程的创建与终止最后简单介绍一下 slab 分派器。 一、进程创建Process creation 1、分叉函数 fork  在  中 fork 函数是非常重要的函数它从已存在进程中创建一个新的进程。  #include unistd.h pid_t fork(void); 新进程为子进程 (child process) 而原进程为父进程 (father process)  返回值子进程中返回 0父进程返回子进程 id出错返回 -1 为什么两个进程的pid不同呢这与fork函数的特性有关。fork调用的一个奇妙之处就是它仅仅被调用一次却能够返回两次它可能有三种不同的返回值     1在父进程中fork返回新创建子进程的进程ID     2在子进程中fork返回0     3如果出现错误fork返回一个负值  在fork函数执行完毕后如果创建新进程成功则出现两个进程一个是子进程一个是父进程。在子进程中fork函数返回0在父进程中fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。 引用一位网友的话来解释fpid的值为什么在父子进程中不同。“其实就相当于链表进程形成了链表父进程的fpid(p 意味point)指向子进程的进程id, 因为子进程没有子进程所以其fpid为0.     fork出错可能有两种原因     1当前的进程数已经达到了系统规定的上限这时errno的值被设置为EAGAIN。     2系统内存不足这时errno的值被设置为ENOMEM。 进程调用 fork当控制转移到内核中的 fork 代码后操作系统会做什么  ①  将给子进程分配新的内存块和内核数据结构 创建 task_struct 和进程地址空间 mm_struct ②  将父进程部分数据结构内容拷贝至子进程 以父进程为模板设置子进程的相关数据结构和父进程相关字段保持一致。    task_struct、地址空间、区域划分很多东西都是一样的。    但不是无脑拷贝比如累计调度的时间片是不一样的。 ③  添加子进程到系统进程列表当中 取决于你进程是要做什么创建后如果状态没问题就会直接链入运行队列中。 ④  fork 返回开始调度器调度 当准备返回时上面三个工作都有了父进程继续执行开始 return子进程也可能执行 fork 的返回值然后就会得到两次返回。 第一次返回的本质通过寄存器向接收变量进行写入写入的本质就是进行修改所以就会发生写时拷贝进而让同一个变量出现不同的值。至此就解释了 fork 的返回值为什么会有两个的问题。 当一个进程调用 fork 之后就有两个二进制代码相同的进程并且它们都运行到相同的地方。 但每个进程都可以开始它们自己的旅程我们来看下面的代码 代码演示 结果 我们可以看到有三行输出两行After一行Before为什么只有一个Before呢30411的Before呢 fork 之前父进程独立执行因为只有父进程。fork 之后父子分道扬镳父子两个执行流分别执行因为 fork 之后有两个进程了。 fork 之后谁先执行谁后执行完全由调度器决定 那么 fork 之后是否只有 fork 之后的代码是被父子进程共享的 实际上fork 之后代码共享这样的说法并不准确。一般情况 fork 之后父子共享所有的代码 子进程执行的后续代码 ! 共享的所有代码只不过子进程只能从这里开始执行 2、写时拷贝copy-on-write  我们知道进程具有独立性代码和数据必须是独立的代码只能读取 → 写时拷贝 通常父子代码共享父子在不让写入时数据也是共享的。当任意一方试图写入就会按照写时拷贝的方式各自拷贝一份副本出来。写时拷贝本身由操作系统的内存管理模块完成的。 操作系统为什么要写时拷贝创建子进程的时候就把数据分开不行吗 有浪费空间之嫌父进程的数据子进程不一定全用即便使用也不一定全部写入。    最理想的情况只有会被父子修改的数据进行分离拷贝。不需要修改的数据共享即可。但是从技术角度实现复杂。    如果 fork 的时候就无脑拷贝数据给子进程会增加 fork 的成本内存和时间 最终采用写时拷贝只会拷贝父子修改的、变相的就是拷贝数据的最小成本。拷贝的成本依旧存在。 写时拷贝实际上以一种 延迟拷贝策略延迟拷贝最大的价值只有真正使用的时候才给你拷。 其最大的意义在于你想要但是不立马使用的空间先不给你那么也就意味着可以先给别人。 反正拷贝的成本总是要有早给你晚给你都是一样。万一我现在给你你又不用那其实不很浪费 所以我选择暂时先不给你等你什么时候要用什么时候再给。这就变相的提高了内存的使用情况。 3、fork 的使用 最简单的方式就是 fork 之后利用 if-else 进行分流 让父子执行不同的代码块。刚才通过实验我们也知道了实际上 if-else 代码也是父进程只不过子进程执行了父进程的代码罢了。所以我们在 fork 之后让父子执行不同的代码段这就是典型地 fork 创建出来让子进程执行类似的事。 一个父进程希望复制自己使父子进程同时执行不同的代码段。我们做网络写服务器的时候会经常采用这样的编码方式例如父进程等待客户端请求生成子进程来处理请求。 还有一种用法就是 fork 之后创建子进程想做和父亲完全不一样的事情比如子进程从 fork 返回后调用 exec 函数。我们本章下面会讲解的 程序地址替换 就和这个有关 4、fork 调用失败的情况  fork 肯定不是永远都成功的fork 也是有可能调用失败的。 系统中有太多进程导致内存资源不足fork 不出。 代码演示我们可以手动演示一下 fork 失败的场景 运行结果如下 二、进程终止Process Termination  1、终止的认识 C/C 的时侯main 函数就是所谓的 入口函数。 但是不知道大家是否关注过这个 return 下面我们思考两个问题 ① 这个 return 0 究竟给谁 return ② 为何是 0 其他值可以吗 #问进程终止的常见方式 运行成功 代码跑完结果正确代码跑完结果不正确运行失败 代码没有跑完程序崩溃了 退出码 #问用代码如何终结一个进程什么是一个正确的终结 0成功正确。非0标识的是运行的结果不正确。 2、进程退出码  写一个main函数return 0并运行可以发现 命令echo $ 最近上一次进程的退出码 因为对于运行结果我们关心的永远是它错了究竟错在哪里、而不是它对了究竟对在哪里。所以用无数的非0值标识不同错误的原因。给我们的程序在运行结束之后对于结果不正确时方便定位错误的原因细节。  如果是再运行一下 就变成0了 $? 表示在  中最近一次执行完毕时对应进程的退出码。 我们随便显示一个不管他存不存在的文件 再反观我们之前学 C 时代码都是无脑 return 0 的…… 而这些指令代码的 return 都是设计好了的 实际上即使不会也没有关系你无脑 return 0return   都没有问题。 3、错误码  C 语言当中有个的 string.h 中有一个 strerror 接口是最经典的、将错误码表述打印出来的接口输出错误原因定义归纳整理如下 #define EPERM 1 /* Operation not permitted */ #define ENOENT 2 /* No such file or directory */ #define ESRCH 3 /* No such process */ #define EINTR 4 /* Interrupted system call */ #define EIO 5 /* I/O error */ #define ENXIO 6 /* No such device or address */ #define E2BIG 7 /* Argument list too long */ #define ENOEXEC 8 /* Exec format error */ #define EBADF 9 /* Bad file number */ #define ECHILD 10 /* No child processes */ #define EAGAIN 11 /* Try again */ #define ENOMEM 12 /* Out of memory */ #define EACCES 13 /* Permission denied */ #define EFAULT 14 /* Bad address */ #define ENOTBLK 15 /* Block device required */ #define EBUSY 16 /* Device or resource busy */ #define EEXIST 17 /* File exists */ #define EXDEV 18 /* Cross-device link */ #define ENODEV 19 /* No such device */ #define ENOTDIR 20 /* Not a directory */ #define EISDIR 21 /* Is a directory */ #define EINVAL 22 /* Invalid argument */ #define ENFILE 23 /* File table overflow */ #define EMFILE 24 /* Too many open files */ #define ENOTTY 25 /* Not a typewriter */ #define ETXTBSY 26 /* Text file busy */ #define EFBIG 27 /* File too large */ #define ENOSPC 28 /* No space left on device */ #define ESPIPE 29 /* Illegal seek */ #define EROFS 30 /* Read-only file system */ #define EMLINK 31 /* Too many links */ #define EPIPE 32 /* Broken pipe */ #define EDOM 33 /* Math argument out of domain of func */ #define ERANGE 34 /* Math result not representable */ #define EDEADLK 35 /* Resource deadlock would occur */ #define ENAMETOOLONG 36 /* File name too long */ #define ENOLCK 37 /* No record locks available */ #define ENOSYS 38 /* Function not implemented */ #define ENOTEMPTY 39 /* Directory not empty */ #define ELOOP 40 /* Too many symbolic links encountered */ #define EWOULDBLOCK EAGAIN /* Operation would block */ #define ENOMSG 42 /* No message of desired type */ #define EIDRM 43 /* Identifier removed */ #define ECHRNG 44 /* Channel number out of range */ #define EL2NSYNC 45 /* Level 2 not synchronized */ #define EL3HLT 46 /* Level 3 halted */ #define EL3RST 47 /* Level 3 reset */ #define ELNRNG 48 /* Link number out of range */ #define EUNATCH 49 /* Protocol driver not attached */ #define ENOCSI 50 /* No CSI structure available */ #define EL2HLT 51 /* Level 2 halted */ #define EBADE 52 /* Invalid exchange */ #define EBADR 53 /* Invalid request descriptor */ #define EXFULL 54 /* Exchange full */ #define ENOANO 55 /* No anode */ #define EBADRQC 56 /* Invalid request code */ #define EBADSLT 57 /* Invalid slot */ #define EDEADLOCK EDEADLK #define EBFONT 59 /* Bad font file format */ #define ENOSTR 60 /* Device not a stream */ #define ENODATA 61 /* No data available */ #define ETIME 62 /* Timer expired */ #define ENOSR 63 /* Out of streams resources */ #define ENONET 64 /* Machine is not on the network */ #define ENOPKG 65 /* Package not installed */ #define EREMOTE 66 /* Object is remote */ #define ENOLINK 67 /* Link has been severed */ #define EADV 68 /* Advertise error */ #define ESRMNT 69 /* Srmount error */ #define ECOMM 70 /* Communication error on send */ #define EPROTO 71 /* Protocol error */ #define EMULTIHOP 72 /* Multihop attempted */ #define EDOTDOT 73 /* RFS specific error */ #define EBADMSG 74 /* Not a data message */ #define EOVERFLOW 75 /* Value too large for defined data type */ #define ENOTUNIQ 76 /* Name not unique on network */ #define EBADFD 77 /* File descriptor in bad state */ #define EREMCHG 78 /* Remote address changed */ #define ELIBACC 79 /* Can not access a needed shared library */ #define ELIBBAD 80 /* Accessing a corrupted shared library */ #define ELIBSCN 81 /* .lib section in a.out corrupted */ #define ELIBMAX 82 /* Attempting to link in too many shared libraries */ #define ELIBEXEC 83 /* Cannot exec a shared library directly */ #define EILSEQ 84 /* Illegal byte sequence */ #define ERESTART 85 /* Interrupted system call should be restarted */ #define ESTRPIPE 86 /* Streams pipe error */ #define EUSERS 87 /* Too many users */ #define ENOTSOCK 88 /* Socket operation on non-socket */ #define EDESTADDRREQ 89 /* Destination address required */ #define EMSGSIZE 90 /* Message too long */ #define EPROTOTYPE 91 /* Protocol wrong type for socket */ #define ENOPROTOOPT 92 /* Protocol not available */ #define EPROTONOSUPPORT 93 /* Protocol not supported */ #define ESOCKTNOSUPPORT 94 /* Socket type not supported */ #define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ #define EPFNOSUPPORT 96 /* Protocol family not supported */ #define EAFNOSUPPORT 97 /* Address family not supported by protocol */ #define EADDRINUSE 98 /* Address already in use */ #define EADDRNOTAVAIL 99 /* Cannot assign requested address */ #define ENETDOWN 100 /* Network is down */ #define ENETUNREACH 101 /* Network is unreachable */ #define ENETRESET 102 /* Network dropped connection because of reset */ #define ECONNABORTED 103 /* Software caused connection abort */ #define ECONNRESET 104 /* Connection reset by peer */ #define ENOBUFS 105 /* No buffer space available */ #define EISCONN 106 /* Transport endpoint is already connected */ #define ENOTCONN 107 /* Transport endpoint is not connected */ #define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ #define ETOOMANYREFS 109 /* Too many references: cannot splice */ #define ETIMEDOUT 110 /* Connection timed out */ #define ECONNREFUSED 111 /* Connection refused */ #define EHOSTDOWN 112 /* Host is down */ #define EHOSTUNREACH 113 /* No route to host */ #define EALREADY 114 /* Operation already in progress */ #define EINPROGRESS 115 /* Operation now in progress */ #define ESTALE 116 /* Stale NFS file handle */ #define EUCLEAN 117 /* Structure needs cleaning */ #define ENOTNAM 118 /* Not a XENIX named type file */ #define ENAVAIL 119 /* No XENIX semaphores available */ #define EISNAM 120 /* Is a named type file */ #define EREMOTEIO 121 /* Remote I/O error */ #define EDQUOT 122 /* Quota exceeded */ #define ENOMEDIUM 123 /* Nomedium found */ #define EMEDIUMTYEP 124 /*Wrongmedium found */ #define ECANCELED 125 /* Operation Canceled */ #define ENOKEY 126 /* Required key not available */ #define EKEYEXPIRED 127 /* Key has expired */ #define EKEYREVOKED 128 /* Key has been revoked */ #define EKEYREJECTED 129 /* Key was rejected by service */ #define EOWNERDEAD 130 /* Owner died */ #define ENOTRECOVERABLE 131 /* State not recoverable */ #define ERFKILL 132 /* Operation not possible due to RF-kill */ #define EHWPOISON 133 /* Memory page has hardware error */ 我们可以在  下写个程式去把这些错误码给打印出来 运行结果如下 会出来很多。。。 其中0 表示 success1 表示权限不允许2 找不到文件或目录。 我们刚才 ls 一个不存在的再 echo $?  显示对应的错误码就是 2 总结错误码退出码可以对应不同的错误原因方便我们定位问题出在哪里。 4、进程终止的常见方法 正常终止可以通过 echo $?  查看进程退出码 ① 从 main 函数返回    ② 调用 exit     ③ _exit 我们先思考两个问题 1. 在 main 函数中的 return为什么其他函数不行 2. 在自己的代码任意地点中调用 exit() 都可以做到进程退出。 该函数想必大家并不陌生exit 并不是一个系统调用而是用 C 写的。 代码演示我们来用一下这个 exit 函数 运行结果如下 运行完之后打印完hello func之后直接结束了程序并没有返回就在函数内部结束了。 从 main 函数调了 func 函数进去打印后执行了 exit最后进程没有返回直接在函数内部直接终止进程这就叫调 exit 直接终止进程。此时我们 echo $? 得到的结果是 111 。 exit 当然也是可以在 main 函数中使用的这里就不演示了。 如果你以后想终止一个进程只需要在任意地点调用 exit 去 代表 进程退出。 注意只有在 main 函数调 return 才叫做 进程退出其他函数调 return 叫做 函数返回。 下面我们再来讲解一下 _exit 函数_exit 也是一个系统调用也是可以用来终止进程的。 exit 和 _exit 是调用和被调用的关系exit 是调用了 _exit 的。代码演示_exit 函数 运行结果如下 区别exit 会清理缓冲区关闭流等操作而 _exit 什么都不干直接终止并返回了我们随意写的退出码100 5、内核数据结构缓冲池 我们知道 进程  内核结构  进程代码和数据 。 内核结构最典型的就是 task_struct 和 mm_struct定义对象后以此充当进程的内核结构。 对于操作系统可能并不会释放该进程的内核数据结构 实际上创建进程我们从零开始构建对象创建对象分为两个步骤即开辟空间与初始化。 无论是开辟空间还是初始化都是要花费时间的存在 cost 的……那该怎么办 会维护一张废弃的数据结构链表我们称之为它是我们链表的数据结构结点。 当进程1释放后进程的相关数据结构会维护进链表中该数据结构是已经被操作系统释放掉了但是并没有把它把它空间释放掉而是设置其为 无效。当你再次创建进程时它会从该队列中把相应的 task_struct 和 mm_struct 取出来这就节省了开辟空间所花费的时间要做的也只是把新进程的代码和空间进行初始化可谓非常的轻松。 这种做法我们称之为 内核的数据结构缓冲池该策略在操作系统中称为 slab 分派器 。 由于内核数据结构高频地使用创建一个进程释放一个进程是特别高频率的事情。 每次开辟空间再初始化难免有些累既然频率高那么索性不再对结构进行重新申请。 直接把数据结构缓存起来要就拿不要就再放回去便利店借雨伞这就是 slab 分配器。
http://www.zqtcl.cn/news/552213/

相关文章:

  • 网站建设的需求要素设计企业网站机
  • 深圳百度推广电话西安官网seo技术
  • 沈阳建站免费模板福州建设企业
  • 怎么在百度首页做网站wordpress返回前页
  • 张家口城乡建设局网站wordpress 等待响应
  • 专门设计网站的公司叫什么怎么做网站多少钱
  • 淡水网站建设健身器材 网站模版
  • 河南建设网站公司简介做新闻类网站需要什么资质
  • 网络文化经营许可证图片下载优化大师安装桌面
  • 网站cms系统教育网站开发文档
  • 用网站做淘客怎么做网站建设在电访销售话术
  • 做电影网站赚了几百万动画制作流程
  • 怎么做企业的网站首页wordpress 主机迁移
  • 网站常见问题网页设计代码开头
  • 聊城网站推广品牌推广计划描述
  • 池州网站制作优化有没有专业做特产的网站
  • wordpress采集站源码wordpress好用的会员插件
  • 寿县城乡建设局网站青岛网站建设大全
  • 杭州做网站的好公司哪家好做影视网站侵权吗
  • 自助建站网站seo公司想学编程做网站
  • 网站空间备案要多久花木公司网站源码
  • 高端求职网站排名ftontpage如何做网站
  • 音乐网站开发技术河南省住房和城乡建设门户网站
  • 吉安微信网站弋阳县建设工程网站
  • 网站建设自学建站视频教程哈尔滨全国网站建设
  • 网站建设基础培训网站架构拓扑图
  • 网站开发价格预算成都必去的地方排行榜
  • 鹤岗做网站企业建立网站主要包括那些流程
  • 如何进网站出口外贸是做什么的
  • 网站制作北京网站建设公司哪家好一个人 建设网站