利用体系之shell实现(上)

[复制链接]
发表于 2025-9-23 04:58:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×

  
🌟 各位看官好,我是maomi_9526!

  
🌍 种一棵树最好是十年前,其次是现在!

  
🚀 本日来学习C语言的干系知识。

  
👍 如果以为这篇文章有资助,欢迎您一键三连,分享给更多人哦

  目次
1. 历程创建
1.1fork函数
​编辑
1.2写时拷贝(Copy-on-write)
1.3 假造地点存储 
2. 历程停止
2.1历程退出环境
2.2退出方式
2.3退出码

2.4exit函数VS_exit函数
2.4.1exit函数
 2.4.2_exit函数
​2.4.3eixt VS_exit​
3. 历程等候
3.1历程等候的须要性
 3.2wait等候
3.3获取子历程status
3.3.1退出码 
3.3.2停止信号 
3.3.3 WIFEXITED
3.3.4WEXITSTATUS
3.4非壅闭查询(wnohang)和壅闭查询(0)
4.总结

1. 历程创建

1.1fork函数

fork() 是 Linux 中非常紧张的函数,用来从父历程创建一个子历程。父历程返回子历程的PID,子历程返回0。通过 fork() 创建的父子历程可以独立执行各自的代码。

   头文件:#include<unistd.h>
  返回值:乐成父历程返回孩子pid,子历程返回0。失败返回-1。
  函数:pid_t frok(void); 
  1. #include<stdio.h>
  2. #include<unistd.h>
  3. int main()
  4. {
  5.     printf("Befor pid is %d\n",getpid());
  6.     pid_t id=fork();
  7.     if(id==-1)
  8.     {
  9.         perror("fork()");
  10.         exit(1);
  11.     }
  12.     printf("After:pid is %d,return id is %d \n",getpid(),id);
  13. }
复制代码
结果: 



1.2写时拷贝(Copy-on-write)

fork() 使父子历程共享相同的内存内容,直到其中一个历程对内存举行修改,这时才会举行拷贝,制止不须要的资源浪费。 

  1. #include<stdio.h>
  2. #include<unistd.h>
  3. #include<sys/types.h>
  4. #include<stdlib.h>
  5. int main()
  6. {
  7.     int a=0;
  8.     printf("Befor pid is %d\n",getpid());
  9.     pid_t id=fork();
  10.     if(id==-1)
  11.     {
  12.         perror("fork()");
  13.         exit(1);
  14.     }
  15.       printf("After:pid is %d,return id is %d \n",getpid(),id);  
  16. }
复制代码
 此时三个地点:a取地点一样

1.3 假造地点存储 

实行在子历程中修改a的地点后,查看a的地点。
  1. #include<stdio.h>
  2. #include<unistd.h>
  3. #include<sys/types.h>
  4. #include<stdlib.h>
  5. int main()
  6. {
  7.     int a=0;
  8.     printf("Befor pid is %d,path is %p\n",getpid(),&a);
  9.     pid_t id=fork();
  10.     if(id==-1)
  11.     {
  12.         perror("fork()");
  13.         exit(1);
  14.     }
  15.     if(id==0)
  16.     {
  17.       a=15;
  18.       printf("After:pid is %d,return id is %d ,path is %p,a is %d\n",getpid(),id,&a,a);  
  19.     }
  20.     else
  21.     printf("After:pid is %d,return id is %d ,path is %p,a is %d\n",getpid(),id,&a,a);
  22. }
复制代码

 三个地点仍旧相同?这是为什么呢?

两个假造地点相同的原因在于它们位于差别的假造页面上,但在各自的假造页面内,偏移量相同。因此,只管它们属于差别的假造内存块,最终的假造地点值却相同。
2. 历程停止

2.1历程退出环境



  • 代码运行完毕,结果正常
  • 代码运行完毕,结果不正常
  • 历程非常停止
2.2退出方式

如果体系正常停止可以通过$?来查看历程退出码


  • 从main函数返回
  • 调用exit
  • 调用_exit
2.3退出码

每个历程都有一个退出码,0 体现正常退出,非 0 体现堕落。



2.4exit函数VS_exit函数

2.4.1exit函数

   #include <unistd.h>
  #include<stdlib.h>
void exit(int status); 
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<unistd.h>
  4. int main()
  5. {
  6.   printf("exit");
  7.   exit(1);
  8. }
复制代码

 2.4.2_exit函数

   #include <unistd.h>
  #include<stdlib.h>
void _exit(int status); 
  1. #include<stdio.h>
  2. #include<unistd.h>
  3. int main()
  4. {
  5.   printf("_exit");
  6.   _exit(1);
  7. }
复制代码
 2.4.3eixt VS_exit



3. 历程等候

3.1历程等候的须要性



  • 之前讲过,子历程退出,父历程如果不管不顾,就大概造成‘僵尸历程’的题目,进而造成内存
  • 走漏。
  • 别的,历程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,由于谁也没有办法杀死一个已经死去的历程。
  • 最后,父历程派给子历程的任务完成的怎样,我们须要知道。如,子历程运行完成,结果对还是不对,大概是否正常退出。
  • 父历程通过历程等候的方式,接纳子历程资源,获取子历程退出信息
 3.2wait等候

   #include <sys/types.h>
  #include <sys/wait.h>
    pid_t wait(int *status);
  返回值:
        乐成返回被等候历程pid,失败返回-1。
参数:
        输出型参数,获取子历程退出状态,不关心则可以设置成为NULL
    pid_t waitpid(pid_t pid, int *status, int options);
  返回值:
        当正常返回的时间waitpid返回网络到的子历程的历程ID;
        如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子历程可网络,则返回0;
        如果调用中堕落,则返回-1,这时errno会被设置成相应的值以指示错误所在;
参数:
        pid:
                Pid=-1,等候任一个子历程。与wait等效。
                Pid>0.等候其历程ID与pid相称的子历程。
        status:
                  输出型参数
                        WIFEXITED(status): 若为正常停止子历程返回的状态,则为真。(查看历程是否是正常退出)
                        WEXITSTATUS(status): 若WIFEXITED非零,提取子历程退出码。(查看历程的退出码)
options:默认为0,体现壅闭等候
                          WNOHANG: 若pid指定的子历程没有竣事,则waitpid()函数返回0,不予以等
待。若正常竣事,则返回该子历程的ID。
    int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
   

3.3获取子历程status

  1. #include<stdio.h>
  2. #include<sys/types.h>
  3. #include<sys/wait.h>
  4. #include<unistd.h>
  5. #include<stdlib.h>
  6. int main()
  7. {
  8.   int id=0;
  9.   int cur=5;
  10.   id=fork();
  11.   if(id==-1)
  12.   {
  13.     perror("fork");
  14.   }
  15.   if(id==0)
  16.   {
  17.     while(cur--)
  18.     {
  19.       printf("My pid is %d,My ppid is %d\n",getpid(),getppid());
  20.     }
  21.     sleep(1);
  22.     exit(1);
  23.   }
  24.   int status=0;
  25.   int idd=waitpid(id,&status,0);
  26.   printf("idd is %d,status is %d\n",idd,status);
  27. }
复制代码

3.3.1退出码 

为什么退出码是256而不是1?

  1.   printf("idd is %d,status is %d\n",idd,(status>>8));
复制代码

3.3.2停止信号 


3.3.3 WIFEXITED

是一个宏值,与&0x7F取得的结果相仿
步伐正常运举动:真
步伐非常退出为:假

3.3.4WEXITSTATUS

是一个宏值,与(>>8)&&0xFF取得的结果雷同

3.4非壅闭等候(wnohang)和壅闭等候(0)

  1. #include<stdio.h>
  2. #include<sys/types.h>
  3. #include<sys/wait.h>
  4. #include<unistd.h>
  5. #include<stdlib.h>
  6. int main()
  7. {
  8.     int id=fork();
  9.     if(id==-1)
  10.     {
  11.         perror("fork error");
  12.     }
  13.     if(id==0)
  14.     {
  15.         int cur=5;
  16.         while(cur--)
  17.         {
  18.             printf("My pid is %d,my ppid is %d\n",getpid(),getppid());
  19.         }
  20.         exit(1);
  21.     }
  22.     //父进程
  23.     int status=0;
  24.     int idd=waitpid(id,&status,0);//阻塞等待
  25.     //int idd=waitpid(id,&status,WNOHANG);//非阻塞等待
  26.     if(idd>0)
  27.     {
  28.         printf("退出码:%d",WEXITSTATUS(status));
  29.     }
  30. }
复制代码
4.总结

 1.Linux下的错误码及形貌
  1. 0->Success
  2. 1->Operation not permitted
  3. 2->No such file or directory
  4. 3->No such process
  5. 4->Interrupted system call
  6. 5->Input/output error
  7. 6->No such device or address
  8. 7->Argument list too long
  9. 8->Exec format error
  10. 9->Bad file descriptor
  11. 10->No child processes
  12. 11->Resource temporarily unavailable
  13. 12->Cannot allocate memory
  14. 13->Permission denied
  15. 14->Bad address
  16. 15->Block device required
  17. 16->Device or resource busy
  18. 17->File exists
  19. 18->Invalid cross-device link
  20. 19->No such device
  21. 20->Not a directory
  22. 21->Is a directory
  23. 22->Invalid argument
  24. 23->Too many open files in system
  25. 24->Too many open files
  26. 25->Inappropriate ioctl for device
  27. 26->Text file busy
  28. 27->File too large
  29. 28->No space left on device
  30. 29->Illegal seek
  31. 30->Read-only file system
  32. 31->Too many links
  33. 32->Broken pipe
  34. 33->Numerical argument out of domain
  35. 34->Numerical result out of range
  36. 35->Resource deadlock avoided
  37. 36->File name too long
  38. 37->No locks available
  39. 38->Function not implemented
  40. 39->Directory not empty
  41. 40->Too many levels of symbolic links
  42. 41->Unknown error 41
  43. 42->No message of desired type
  44. 43->Identifier removed
  45. 44->Channel number out of range
  46. 45->Level 2 not synchronized
  47. 46->Level 3 halted
  48. 47->Level 3 reset
  49. 48->Link number out of range
  50. 49->Protocol driver not attached
  51. 50->No CSI structure available
  52. 51->Level 2 halted
  53. 52->Invalid exchange
  54. 53->Invalid request descriptor
  55. 54->Exchange full
  56. 55->No anode
  57. 56->Invalid request code
  58. 57->Invalid slot
  59. 58->Unknown error 58
  60. 59->Bad font file format
  61. 60->Device not a stream
  62. 61->No data available
  63. 62->Timer expired
  64. 63->Out of streams resources
  65. 64->Machine is not on the network
  66. 65->Package not installed
  67. 66->Object is remote
  68. 67->Link has been severed
  69. 68->Advertise error
  70. 69->Srmount error
  71. 70->Communication error on send
  72. 71->Protocol error
  73. 72->Multihop attempted
  74. 73->RFS specific error
  75. 74->Bad message
  76. 75->Value too large for defined data type
  77. 76->Name not unique on network
  78. 77->File descriptor in bad state
  79. 78->Remote address changed
  80. 79->Can not access a needed shared library
  81. 80->Accessing a corrupted shared library
  82. 81->.lib section in a.out corrupted
  83. 82->Attempting to link in too many shared libraries
  84. 83->Cannot exec a shared library directly
  85. 84->Invalid or incomplete multibyte or wide character
  86. 85->Interrupted system call should be restarted
  87. 86->Streams pipe error
  88. 87->Too many users
  89. 88->Socket operation on non-socket
  90. 89->Destination address required
  91. 90->Message too long
  92. 91->Protocol wrong type for socket
  93. 92->Protocol not available
  94. 93->Protocol not supported
  95. 94->Socket type not supported
  96. 95->Operation not supported
  97. 96->Protocol family not supported
  98. 97->Address family not supported by protocol
  99. 98->Address already in use
  100. 99->Cannot assign requested address
  101. 100->Network is down
  102. 101->Network is unreachable
  103. 102->Network dropped connection on reset
  104. 103->Software caused connection abort
  105. 104->Connection reset by peer
  106. 105->No buffer space available
  107. 106->Transport endpoint is already connected
  108. 107->Transport endpoint is not connected
  109. 108->Cannot send after transport endpoint shutdown
  110. 109->Too many references: cannot splice
  111. 110->Connection timed out
  112. 111->Connection refused
  113. 112->Host is down
  114. 113->No route to host
  115. 114->Operation already in progress
  116. 115->Operation now in progress
  117. 116->Stale file handle
  118. 117->Structure needs cleaning
  119. 118->Not a XENIX named type file
  120. 119->No XENIX semaphores available
  121. 120->Is a named type file
  122. 121->Remote I/O error
  123. 122->Disk quota exceeded
  124. 123->No medium found
  125. 124->Wrong medium type
  126. 125->Operation canceled
  127. 126->Required key not available
  128. 127->Key has expired
  129. 128->Key has been revoked
  130. 129->Key was rejected by service
  131. 130->Owner died
  132. 131->State not recoverable
  133. 132->Operation not possible due to RF-kill
  134. 133->Memory page has hardware error
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表