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

电影网站建设步骤网站成品作业

电影网站建设步骤,网站成品作业,网站建设的建议和意见,wordpress搜索增加条件#x1f923; 爆笑教程 #x1f449; 《看表情包学Linux》#x1f448; 猛戳订阅 #x1f525; #x1f4ad; 写在前面#xff1a;在上一章中我们讲解了进程创建与进程终止#xff0c;本章我们开始讲解进程等待。进程等待这部分知识相较于前面还是较为复杂的#xff0…   爆笑教程  《看表情包学Linux》 猛戳订阅   写在前面在上一章中我们讲解了进程创建与进程终止本章我们开始讲解进程等待。进程等待这部分知识相较于前面还是较为复杂的我会由浅入深地讲解这部分的知识点值得一提的是在学习本章前需要掌握进程状态的知识复习链接我会贴到下面。我们先谈论进程等待的必要性简单地讲解 wait 函数然后我们主要讲解 waitpid 函数。由于 wait 只有一个参数 status且 waitpid 有三个参数且其中一个也是 status我们本章重点讲解这个 status 参数。因为要控制篇幅本章没办法讲清楚 waitpid 的其余参数比如 options 参数我们将放到后期讲解所以算是对 waitpid 函数的一个初探后面我们还会继续讲解它的。 前置知识【看表情包学Linux】进程状态 Ⅰ. 进程等待Process wait 0x00 引入进程等待的必要性 ❓ 为什么要进行进程等待不知道大家是否还记得我们在之前的章节讲过的 僵尸进程 的概念。 僵尸状态当一个  中的进程退出的时候一般不会直接进入  状态死亡资源可以立马被回收而是进入  状态。 子进程退出如果父进程不管不顾就 可能造成僵尸进程的问题一直占内存进而引发内存泄露。 这是典型的占着茅坑不拉翔行为 此外进程一旦变成僵尸状态就会变得刀枪不入不可被杀因为我们说过 甚至 杀进程不眨眼的 kill -9 也无法奈其何 所以我们必须让其从  状态变为  状态 进而允许操作系统能去释放它将代码和数据 free 掉将相关数据结构归还给 slab 分派器。 上面我们讲的实际上就是我们需要进程等待的一个原因 —— 解决内存泄露问题 。 然而不仅仅这一个原因我们还需要进程等待来 获取子进程的退出状态 。 我们需要知道父进程派给子进程的任务完成的如何。 比如子进程运行完成结果对还是不对是否正常退出 通过进程等待的方式回收子进程资源获得子进程退出信息。 当然了并不是所有的父进程需要关心子进程的。所以是存在父进程不等待子进程的情况的处理的方案我们在之前也有所铺垫该部分话题我们会在后期讲信号的时候进一步讲解。本章我们只关心父进程必须等待子进程的情况解决僵尸进程问题让子进程尽快恢复获取子进程的退出状态 获取子进程的退出状态是否需要将曾经子进程的退出信息保存起来然后被恢复、读取呢 这和我们刚才讲的进程退出有着大大的关系我们知道了进程退出是有退出码的。 我们需要让子进程退出时它的 return 结果或者 exit 的结果是需要被父进程读到的。 总结需要进程等待的原因① 解决内存泄露问题     ② 获取子进程的退出状态 0x01 wait 函数 说得好那么如何等待呢 我们先来介绍一下 wait 函数。第一种方式就是让父进程调用 wait 即可。 wait() 可以解决回收子进程  状态让子进程进入  状态。 #include sys/types.h #include sys/wait.hpid_t wait(int* status); 我们看到wait 有一个叫 status 的参数我们暂时不说下面讲 waitpid 后会详细讲解 我们下面验证一下这个函数是否可以 我们会把 status 暂且设置为空。 验证调用  函数回让父进程 礼貌地 等待子进程 #include stdio.h #include unistd.h #include stdlib.h #include string.h #include sys/types.h #include sys/wait.hint main (void) {pid_t id fork();if (id 0) {// childwhile (1) {printf(我是子进程我正在运行... Pid: %d\n, getpid());sleep(1);}}else {printf(我是父进程: pid: %d我将耐心地等待子进程\n, getpid());sleep(20); // 为了便于观察我们让父进程休眠20s// 苏醒后父进程执行 wait耐心地等待子进程pid_t ret wait(NULL); // 暂且将status参数设置为NULLif (ret 0) {printf(等待失败\n);}else {printf(等待成功\n); // 此时 Z → X}sleep(20); // 子进程退出后再让父进程存在一段时间} }说明简单来说就是让父子进程都跑起来并各自打印消息子进程一直死循环运行父进程将自己休眠 20 秒在这 20 秒之内我们手动把处于死循环的子进程给 kill 掉此时子进程会处于  状态此时父进程还在休眠不会立即调用 wait这么做是为了便于观察。 当 20 秒过后父进程苏醒后执行了 wait 函数用一个变量 ret 去接收 wait 的返回值通过返回值来确定是否等待成功。如果等待成功了就会成功 。 为了观察进程状态我们写一段监控脚本做到每隔一秒就监控一下我们的 mytest 进程。 监控脚本 $ while :; do ps ajx | head -1 ps ajx | grep mytest | grep -v grep; echo -----------------------------------------------------------------------; sleep 1; done运行后我们只需要死死盯着 观察状态的变化即可 开三个窗口分别用于运行监控脚本、运行 mytest 和 kill 子进程 开始运行 ./mytest 至此我们成功验证了父进程等待了子进程。 通过 wait() 的方案我们可以解决回收子进程的  状态让子进程进入  状态。 0x02 waitpid 函数初探 刚才讲的 wait 并不是主角因为其功能比较简单在进程等待时用的更多的是 waitpid waitpid 可以把 wait 完全包含wait 是 waitpid 的一个子功能。 注意wait/waitpid 都可以回收子进程的僵尸状态。 waitpid等待任意一个退出的子进程。 #include sys/types.h #include sys/wait.hpid_t waitpid(pid_t pid, int* status, int options); 对于返回值 pid_t 如果 pid_t 0等待子进程成功返回值就是子进程的 pid如果 pid_t 0等待失败。 对于参数 pid 设置参数 pid 0是几就代表等待哪一个子进程比如 pid1234指定等待。设置参数 pid  -1待任意进程。 对于参数 options 0阻塞等待   本章不讲 对于参数 status 该参数是一个输出型参数通过调用该函数从函数内部拿出特定的数据。 本章我们将重点讲解参数 status 值得强调的是wait/waitpid 是系统调用 说明父进程等待子进程子进程也会执行自己的代码。当子进程执行了 return/exit 退出后子进程会将自己的退出码信息写入自己的进程控制块 () 中。子进程退出了代码可以释放子进程退出后变成  状态其本质上就是将自己的 task_struct 维护起来代码可以释放但是 task_struct 必须维护。所谓的 wait/waitpid 的退出信息实际上就是从子进程的 task_struct 中拿出来的即 从子进程的 task_struct 中拿出子进程退出的退出码。 所以我们的父进程在等待子进程死亡等子进程一死就直接把子进程的退出码信息拷贝过去通过 wait/waitpid 传进来的参数后父进程就拿到了子进程的退出结果。即 子进程会将自己的退出信息写入 task_struct  。 子进程的 task_struct 是操作系统的内部数据结构这个 waitpid 自然就是系统调用实际上就是调用操作系统的功能。 那……这个 status 仅仅只是一个无情的拿退出码的机器吗 当然不是肯定还会包含其他信息的这个我们一会讲解。 我们再来验证一下 子进程会将自己的退出信息写入 task_struct 这句话 解读这里我们可以看到 exit_state这就是退出状态了下面的 exit_code 和 exit_signal 分别是退出码和退出信号当一个进程异常退出时该进程会收到信号所以收到的信号编号也记录在了这里。这两个信息会在子进程任何地方退出时填充被填充后父进程就可以读取 task_struct 中的这两个数据来得到子进程的退出结果。 总结父进程通过调用 wait/waitpid通过 status 参数就可以将子进程的信息拿到手。 由此可见这个 status 是多么的重要我们现在就来重点来讲解一下 status Ⅱ. 详解 wait/waitpid 的 status 参数 0x00 引入status 参数是位图结构 wait 和 waitpid都有这个 status 参数我们刚才演示 wait 的时候传的是 NULL 如果传递 NULL则表示不关心子进程的退出状态信息。否则操作系统会根据该参数将子进程的退出信息反馈给父进程。 该参数是一个 输出型参数 即通过调用该函数从函数内部拿出来特定的数据。 并且status 参数是由操作系统填充的是一个整数该整数就是下面我们要详细研究的。 它虽然是一个 int 型整数但是不能简单地将其看作整型而是被当作一个 位图结构 看待。 不过关于 status 我们只需要关心该整数的 低 16 个比特位 我们不必去关心它的高 16 位因为凭借低 16 位就足以判断了。 然而整数的低 16 位其中又可以分为 最低八位 和 次低八位具体细节看图 那么我们你可以通过它们来干什么呢我们先来讲解低十六位中的 次低八位 。 0x01 次低八位拿子进程退出码 重点通过提取 status 的次低八位就可以拿到子进程的退出码。 验证 通过提取 status 的次低八位可以拿到子进程的退出码。 #include stdio.h #include unistd.h #include stdlib.h #include string.h #include sys/types.h #include sys/wait.hint main (void) {pid_t id fork();if (id 0) {int cnt 5; // 循环5次// childwhile (1) {// 五秒之内运行状态printf(我是子进程我正在运行... Pid: %d\n, getpid());sleep(1);// 五秒之后子进程终止cnt--;if (cnt 0) {break; }}exit(233); // 方便辨识退出码我们设置为233这是我们的预期结果}else {printf(我是父进程: pid: %d我将耐心地等待子进程\n, getpid());// ***** 使用waitpid进行进程等待int status 0; // 接收 waitpid 的 status 参数pid_t ret waitpid(id, status, 0);if (ret 0) { // 等待成功printf (等待成功ret: %d, 我所等待的子进程退出码: %d\n, ret,(status8)0xFF);}} } 说明我们让 child 子进程运行五秒后自动结束之后通过 exit 返回为了方便辨识我们可以将退出码设置的花一点这里我设置了个 233。父进程调用 waitpid 函数并用 ret 接收如果返回值大于 0 则代表等待成功此时我们打印出子进程的退出码因为 通过提取 status 的次低八位就可以拿到子进程的退出码。 所以我们可以通过 status 参数去拿。 我们说了status 并不是整体使用的而是区域性使用的我们要取其次低八位。我们可以用 位操作 来完成将 status 右移八位再按位与上 即 (status8)0xFF 就可以提取到 status 的次低八位了。 如果不出意外的话运行后 waitpid 等待成功子进程的返回值应当是 233就证明了可以通过提取 status 的次低八位拿到子进程的退出码。 运行结果如下 0x02 初识 core dump核心转储 由于还没有讲解信号的部分的知识我们先做一个简单的了解 我们看到core dump 是占了 1 个 比特位的 core dump 指的是 核心转储也可以称之为 吐核。 它是操作系统在进程收到某些信号而终止运行时将此时进程地址空间的内容以及有关进程状态的其他信息写出的一个磁盘文件。目前只需要知道该信息是用于调试的。 0x03 最低七位提取子进程的退出信号 重点通过提取 status 的最低七位就可以拿到子进程的退出信号。 我们的 status 的低八位用于表示处理异常的地方其中有 1 位是 core dump我们下面讲。 除去 core dump剩余七位用于进程中的退出信号这就是 最低七位。 进程退出如果异常退出是因为这个进程收到了特定的信号。 我们虽然还没有开始讲解信号但是我们前几张就介绍了 kill -9 这样的杀进程操作。 这个 -9 我们当时说了就是一个信号发送该信号也确实可以终止进程。 刚才我们讲的 wait/waitpid 和次低八位的时侯都是关于进程的 正常退出。 如果进程 异常退出 呢我们来模拟一下进程的异常退出。 代码演示模拟异常退出的情况让子进程一直跑父进程一直等。 #include stdio.h #include unistd.h #include stdlib.h #include string.h #include sys/types.h #include sys/wait.hint main (void) {pid_t id fork();if (id 0) {// 子进程一直不退出父进程会一直等待。// childwhile (1) {printf(我是子进程我正在运行... Pid: %d\n, getpid());sleep(1);}exit(13);}else {printf(我是父进程: pid: %d我将耐心地等待子进程\n, getpid());int status 0;pid_t ret waitpid(id, status, 0);if (ret 0) { // 等待成功printf(等待成功ret: %d, 我所等待的子进程退出码: %d\n, 退出信号是: %d, ret, (status8)0xFF, status0x7F);}} }说明现在我们直接 while(1) 死循环让子进程往死里跑此时父进程由于调用了 waitpid就会一直等待子进程父进程就会持续阻塞。 此时我们讲父进程打印的消息再增添一个 退出信号也就是提取 status 的最低七位我们想让低七位保留高二十五位保留让 status 按位与上  即可即 status0x7F  (低七位保留高二十五位全部清零) 。如此一来我们就提取到了子进程退出时的退出信号了。 运行结果如下 因为子进程是个死循环父进程又调了 waitpid导致父进程一直在 阻塞式 地等待子进程。 父进程在等待子进程期间什么都没有干就搬了张板凳坐在那等子进程死。 父进程就像在一直在问子进程 你寄没寄你寄没寄你寄没寄  我们知道信号是可以杀掉进程的我们现在主动输入 kill -9 此时我们就成功拿到了子进程的退出信号9 是因为我们输入的信号就是 9。 此时父进程看到子进程寄了终于可以不用等了可以给子进程收尸了 父进程大喊道  你终于寄了寄你太美oh baby寄你太美寄你实在太美 还是那句话代码跑完结果是什么已经不重要了我们最关心的是因为什么原因退出的。 当进程收到信号时就代表进程异常了。进程程出如果是异常退出是因为该进程收到了特定的信号。其实除了 9 号信号还有很多信号输入 kill -l 就可以查看这些 比如我们遇到的除零警告即  warning: division by zero int a 10 / 0; 这时出现 8 号退出信号 Float Pointer Error 实际上我们在编程学习中遇到的程序崩溃崩溃程序就退出了程序一崩溃程序就退出了今天在我们操作系统的角度来看这就是进程终止。其实是因为错误而导致了软硬件错误操作系统通过发送信号的方式把进程杀掉了。至于操作系统凭什么可以终止 又是怎么发信号的又是如何终止的详细的过程是什么这些问题我们会放到后面的信号章节再做详细讲解 总结退出信号代表进程是否异常退出码代表进程在退出之时代码对还是不对。 0x04 进程退出的宏 我们今天写的代码是通过位操作去截 status 得到退出码和退出信号的。 实际上你也可以不用位操作因为  已经给我们提供了一些宏供我们直接调用。 它们是 WEXITSTATUS 和 WIFEEXITED在这之前我们再思考一个问题 ❓ 思考一个进程退出时可以拿到退出码和推出信号我们先看谁 一旦程序发现异常我们只关心退出信号退出码没有任何意义。 所以我们先关注退出信号如果有异常了我们再去关注退出码。 WEXITSTATUS 宏用于查看进程的退出码若非 0提取子进程退出码。 WEXITSTATUS(status) WIFEEXITED 宏用于查看进程是否正常退出如果是正常终止的子进程返回状态则为真。 WIFEXITED(status) 所以我们可以通过宏来获取退出码和退出信号是不是很方便 代码演示运用 WEXITSTATUS 和 WIFEXITED 宏 else {printf(我是父进程: pid: %d我将耐心地等待子进程\n, getpid());int status 0;pid_t ret waitpid(id, status, 0);if (ret 0) { // 等待成功if (WIFEEXITED(status)) {printf(子进程正常退出退出码: %d\n, WEXITSTATUS(status));}}} 当然了如果你压根就不关注推出信息和退出码你直接把 status 设置为 NULL 就行。 options 参数 默认为 0表示阻塞等待。 当我们调用某些函数的时侯因为条件不就绪需要我们阻塞等待。 本质就是当前进程自己变成阻塞状态等条件就绪的时候再被唤醒。 所谓的阻塞本质就是进程阻塞。所谓的条就不就绪可能是任意的软硬件条件。 还有一个非阻塞等待的知识点我们放到后面再说吧。 [ 笔者 ]   王亦优[ 更新 ]   2022.3.4 ❌ [ 勘误 ]   /* 暂无 */[ 声明 ]   由于作者水平有限本文有错误和不准确之处在所难免本人也很想知道这些错误恳望读者批评指正 参考资料  Creference[EB/OL]. []. http://www.cplusplus.com/reference/. Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. . 百度百科[EB/OL]. []. https://baike.baidu.com/. 比特科技. Linux[EB/OL]. 2021[2021.8.31 xi
http://www.w-s-a.com/news/561144/

相关文章:

  • 湛江网站优化快速排名wordpress文章页面宽度
  • 自己建网站怎么弄唯品会一家专门做特卖的网站
  • 做文化传播公司网站做搜狗pc网站点
  • 免费的黄冈网站有哪些平台可以聊天呢要查询一个网站在什么公司做的推广怎么查
  • 凡客建站登录入口网站建设先进部门评选标准
  • 响应式设计 手机网站政务中心建设网站
  • 如何做卖衣服的网站网站登录接口怎么做
  • 网站源码下载了属于侵权吗499全包网站建设
  • 怎样创建网站信息平台网络推广官网首页
  • 网站建设的课程网站 逻辑结构
  • 开通企业网站搬瓦工暗转wordpress
  • 成都网站建设有名的公司怎么做出有品牌感的网站
  • 中国网站的建设淘宝数据网站开发
  • 深圳建站网站模板wordpress 文章最长
  • 服务器建立网站建网站做seo
  • 帮人做彩票网站支付接口网上请人做软件的网站
  • 万全网站建设wl17581做旅游广告在哪个网站做效果好
  • 钢城网站建设安徽省住房和城乡建设厅网站
  • 协会网站建设方案大良营销网站建设好么
  • 网站引导页一般是什么格式网页设计师的应聘岗位
  • 构建网站空间网站开发与维护招聘
  • 网站建设的网页怎么做番禺网站开发哪家强
  • 网站开发是程序员吗百度网盘下载电脑版官方下载
  • 中国电力建设集团网站杭州网站运营
  • 大气网站模板下载效果好的网站建设公
  • 住房和城乡建设部网站打不开重庆市建设工程信息网官网30系统
  • 做美食软件视频网站大数据精准营销策略
  • 网站后台密码错误陕西大型网站建设
  • 网站建站中关键字搜索怎么弄wordpress 后台插件无法访问
  • 做减肥餐的网站网站优化注意事项