-
Notifications
You must be signed in to change notification settings - Fork 0
/
local-search.xml
33 lines (15 loc) · 98 KB
/
local-search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>ubuntu创建应用的快捷方式</title>
<link href="/2024/10/21/ubuntu%E5%88%9B%E5%BB%BA%E5%BA%94%E7%94%A8%E7%9A%84%E5%BF%AB%E6%8D%B7%E6%96%B9%E5%BC%8F-1/"/>
<url>/2024/10/21/ubuntu%E5%88%9B%E5%BB%BA%E5%BA%94%E7%94%A8%E7%9A%84%E5%BF%AB%E6%8D%B7%E6%96%B9%E5%BC%8F-1/</url>
<content type="html"><![CDATA[<p><strong>在ubuntu上我们通过deb包安装的软件可能会没有快捷方式,这个时候就需要我们自己在终端上创建快捷方式了。</strong></p><p><strong>主要流程有以下几步,这里我们以go语言的IDE goland为例</strong></p><h1 id="1-创建对应的desktop文件"><a href="#1-创建对应的desktop文件" class="headerlink" title="1.创建对应的desktop文件"></a>1.创建对应的desktop文件</h1><p>比如goland,我们需要在/usr/share/applications目录下创建goland.desktop</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs c">cd /usr/share/applications <br>sudo nano /goland.desktop<br></code></pre></td></tr></table></figure><h1 id="2-编辑这个文件"><a href="#2-编辑这个文件" class="headerlink" title="2.编辑这个文件"></a>2.编辑这个文件</h1><p>把这个文件编辑一下,记得要加sudo</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs c">sudo vim goland.desktop<br></code></pre></td></tr></table></figure><p>内容如下</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs c">[Desktop Entry]<br>Version=<span class="hljs-number">1.0</span><br>Type=Application<br>Name=XXX<span class="hljs-comment">//这里输你的应用的名称</span><br>Exec=/path/to/GoLand/bin/goland.sh<span class="hljs-comment">//这里输你的应用的实际路径</span><br>Icon=/path/to/GoLand/bin/goland.png<span class="hljs-comment">//这里输你的应用要用的图标的路径</span><br>Terminal=<span class="hljs-literal">false</span><br></code></pre></td></tr></table></figure><h1 id="3-更改文件的权限"><a href="#3-更改文件的权限" class="headerlink" title="3.更改文件的权限"></a>3.更改文件的权限</h1><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs c">sudo chown xxx Goland.desktop<span class="hljs-comment">//xxx是你的用户名</span><br>sudo chmod <span class="hljs-number">755</span> Goland.desktop/修改权限<br></code></pre></td></tr></table></figure><h1 id="4-把这个文件复制一份到你的桌面"><a href="#4-把这个文件复制一份到你的桌面" class="headerlink" title="4.把这个文件复制一份到你的桌面"></a>4.把这个文件复制一份到你的桌面</h1><p>用cp命令复制</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs c">cp goland.desktop ~/桌面<br></code></pre></td></tr></table></figure><h1 id="5-将你桌面那个文件改为可运行"><a href="#5-将你桌面那个文件改为可运行" class="headerlink" title="5.将你桌面那个文件改为可运行"></a>5.将你桌面那个文件改为可运行</h1><p>直接右键,然后找到“允许运行”点击即可</p>]]></content>
</entry>
<entry>
<title>如何在GNU/Linux下实现自己的shell</title>
<link href="/2024/03/28/%E5%A6%82%E4%BD%95%E5%9C%A8GNU-Linux%E4%B8%8B%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%B7%B1%E7%9A%84shell/"/>
<url>/2024/03/28/%E5%A6%82%E4%BD%95%E5%9C%A8GNU-Linux%E4%B8%8B%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%B7%B1%E7%9A%84shell/</url>
<content type="html"><![CDATA[<h3 id="TASK"><a href="#TASK" class="headerlink" title="TASK"></a>TASK</h3><p>打造一个绝无伦比的 <code>xxx-super-shell</code> (<code>xxx</code> 是你的名字),它能实现下面这些功能:</p><ul><li><p>实现 <strong>管道</strong> (也就是 <code>|</code>)</p></li><li><p>实现 <strong>输入输出重定向</strong>(也就是 </p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">< <br></code></pre></td></tr></table></figure><figure class="highlight node-repl"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs node-repl"><span class="hljs-meta prompt_">></span><br></code></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell"><span class="hljs-meta prompt_">></span><span class="language-bash">></span><br></code></pre></td></tr></table></figure><p>)</p><ul><li>要求实现 在管道组合命令的两端实现重定向运算符</li></ul><figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-comment"># Require </span><br><span class="hljs-attribute">cat</span> < <span class="hljs-number">1</span>.txt | grep -C <span class="hljs-number">10</span> abc | grep -L efd | tac >> <span class="hljs-number">2</span>.txt<br><span class="hljs-comment"># Does not require</span><br><span class="hljs-attribute">cat</span> < <span class="hljs-number">1</span>.txt | grep -C <span class="hljs-number">10</span> abc > test1.txt | test2.txt > grep -L efd | tac >> <span class="hljs-number">2</span>.txt<br></code></pre></td></tr></table></figure></li><li><p>实现 <strong>后台运行</strong>(也就是 <code>&</code> )</p></li><li><p>实现 **<code>cd</code>**,要求支持能切换到绝对路径,相对路径和支持 <code>**cd -**</code></p></li><li><p>屏蔽一些信号(如 <code>ctrl + c</code> 不能终止)</p></li><li><p>界面美观</p></li><li><p>开发过程记录、总结、发布在个人博客中</p></li></ul><p>要求:</p><ul><li>不得出现内存泄漏,内存越界等错误</li><li>学会如何使用 gdb 进行调试,使用 valgrind 等工具进行检测</li></ul><h4 id="测试用例"><a href="#测试用例" class="headerlink" title="测试用例"></a>测试用例</h4><figure class="highlight elixir"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs elixir">xxx<span class="hljs-variable">@xxx</span> ~ <span class="hljs-variable">$ </span>./xxx-super-shell<br>xxx<span class="hljs-variable">@xxx</span> ~ <span class="hljs-variable">$ </span>echo <span class="hljs-title class_">ABCDEF</span><br>xxx<span class="hljs-variable">@xxx</span> ~ <span class="hljs-variable">$ </span>echo <span class="hljs-title class_">ABCDEF</span> > ./<span class="hljs-number">1</span>.txt<br>xxx<span class="hljs-variable">@xxx</span> ~ <span class="hljs-variable">$ </span>cat <span class="hljs-number">1</span>.txt<br>xxx<span class="hljs-variable">@xxx</span> ~ <span class="hljs-variable">$ </span>ls -t >> <span class="hljs-number">1</span>.txt<br>xxx<span class="hljs-variable">@xxx</span> ~ <span class="hljs-variable">$ </span>ls -a -l | grep abc | wc -l > <span class="hljs-number">2</span>.txt<br>xxx<span class="hljs-variable">@xxx</span> ~ <span class="hljs-variable">$ </span>python < ./<span class="hljs-number">1</span>.py | wc -c<br>xxx<span class="hljs-variable">@xxx</span> ~ <span class="hljs-variable">$ </span>mkdir test_dir<br>xxx<span class="hljs-variable">@xxx</span> ~/test_dir <span class="hljs-variable">$ </span>cd test_dir<br>xxx<span class="hljs-variable">@xxx</span> ~ <span class="hljs-variable">$ </span>cd -<br>xxx<span class="hljs-variable">@xxx</span> ~/test_dir <span class="hljs-variable">$ </span>cd -<br>xxx<span class="hljs-variable">@xxx</span> ~ <span class="hljs-variable">$ </span>./xxx-super-shell <span class="hljs-comment"># shell 中嵌套 shell</span><br>xxx<span class="hljs-variable">@xxx</span> ~ <span class="hljs-variable">$ </span>exit<br>xxx<span class="hljs-variable">@xxx</span> ~ <span class="hljs-variable">$ </span>exit<br></code></pre></td></tr></table></figure><ul><li>核心为掌握<code>Linux系统编程</code>中<code>进程</code>的部分</li></ul><h3 id="框架主体"><a href="#框架主体" class="headerlink" title="框架主体"></a>框架主体</h3><h4 id="main"><a href="#main" class="headerlink" title="main()"></a><strong>main</strong>()</h4><p>从main函数来分析实现的整体框架</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-type">int</span> <span class="hljs-title function_">main</span><span class="hljs-params">()</span>{<br> signal(SIGINT,SIG_IGN);<span class="hljs-comment">//屏蔽ctrl+c</span><br> signal(SIGTSTP,SIG_IGN); <span class="hljs-comment">//屏蔽ctrl+z</span><br> <span class="hljs-keyword">while</span>(<span class="hljs-number">1</span>){<br> <span class="hljs-type">char</span>*argv[MAX]={<span class="hljs-literal">NULL</span>};<br> printname();<br> <span class="hljs-type">char</span>*command=readline(<span class="hljs-string">" "</span>);<span class="hljs-comment">//readline函数输出给出的字符串并读取一行输入,并为读取的输入动态分配内存,返回值为指向读取输入的指针</span><br> <span class="hljs-keyword">if</span> (command == <span class="hljs-literal">NULL</span>) <span class="hljs-keyword">continue</span>;<span class="hljs-comment">//屏蔽ctrl+d </span><br> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strlen</span>(command) == <span class="hljs-number">0</span>) <span class="hljs-keyword">continue</span>;<span class="hljs-comment">//回车不爆栈</span><br> <span class="hljs-type">int</span> argc=<span class="hljs-number">1</span>; <br> argv[<span class="hljs-number">0</span>] = strtok(command, <span class="hljs-string">" "</span>);<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i=<span class="hljs-number">1</span>;argv[i] = strtok(<span class="hljs-literal">NULL</span>, <span class="hljs-string">" "</span>);i++) argc++;<span class="hljs-comment">//将命令行输入分割为多个命令</span><br> analyze_cmd(argc,argv);<span class="hljs-comment">//解析命令</span><br> do_cmd(argc,argv);<span class="hljs-comment">//实现命令</span><br> <span class="hljs-built_in">free</span>(command); <span class="hljs-comment">//释放空间</span><br> clear_para();<span class="hljs-comment">//重置参数</span><br> }<br>}<br></code></pre></td></tr></table></figure><ul><li><p>一些声明如MAX可以结合文章最后的全部代码查看</p></li><li><p>首先要调用<code>signal函数</code>屏蔽一些信号</p></li><li><p>由于shell是<code>交互进程</code>(进程分类[<a href="https://blog.csdn.net/xjw8396761/article/details/106486008?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171136764316800225529777%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=171136764316800225529777&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-106486008-null-null.142%5Ev99%5Epc_search_result_base6&utm_term=%E7%B3%BB%E7%BB%9F%E8%BF%9B%E7%A8%8B&spm=1018.2226.3001.4187">详见此博客</a>),所以我们进入while(1)循环,注意,这里的argc和argv不是main函数的参数,而是我们自定义的参数,意义和main函数的参数类似。</p></li><li><p>printname函数负责每次输入命令前和后的终端名字显示和路径显示,具体下文给出。</p></li><li><p>这里使用了一个动态链接库readlilne,需要我们单独下载并通过相应头文件使用,<a href="https://blog.csdn.net/YinJianxiang/article/details/78951123?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171136863216800197033038%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=171136863216800197033038&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-13-78951123-null-null.142%5Ev99%5Epc_search_result_base6&utm_term=readline%E5%BA%93&spm=1018.2226.3001.4187">具体点击这里</a>。功能有很多,我们这里用到的是readline()函数读取输入和显示历史命令</p></li><li><p>整体框架已经有了,下面给出各个部分的详细解释</p></li></ul><h3 id="接口详解"><a href="#接口详解" class="headerlink" title="接口详解"></a>接口详解</h3><h4 id="printname"><a href="#printname" class="headerlink" title="printname()"></a>printname()</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-type">void</span> <span class="hljs-title function_">printname</span><span class="hljs-params">()</span>{<br> <span class="hljs-type">char</span> pathname[PATHMAX];<br> getcwd(pathname,PATHMAX);<span class="hljs-comment">//获取当前目录</span><br> <span class="hljs-built_in">printf</span>(BLUE<span class="hljs-string">"Whosefrienda-shell"</span>CLOSE);<span class="hljs-comment">//打印shell名称</span><br> <span class="hljs-built_in">printf</span>(GREEN<span class="hljs-string">" :%s"</span>CLOSE,pathname);<span class="hljs-comment">//打印路径</span><br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"$ "</span>);<br> fflush(<span class="hljs-built_in">stdout</span>);<span class="hljs-comment">//清除缓冲区</span><br>}<br></code></pre></td></tr></table></figure><ul><li><p>具体注释有解释,(下文代码也是主要看注释,特殊的具体解释)这里只说一下这个BLUE和GREEN和CLOSE是通过宏定义实现的,定义如下</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-meta">#<span class="hljs-keyword">define</span> BLUE <span class="hljs-string">"\033[34m"</span><span class="hljs-comment">//宏定义实现有色字体</span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> GREEN <span class="hljs-string">"\033[32m"</span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> CLOSE <span class="hljs-string">"\033[0m"</span></span><br></code></pre></td></tr></table></figure></li></ul><h4 id="analyze-cmd-argc-argv"><a href="#analyze-cmd-argc-argv" class="headerlink" title="analyze_cmd(argc,argv)()"></a>analyze_cmd(argc,argv)()</h4><p>这里用了全局变量</p><figure class="highlight abnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs abnf">int cd <span class="hljs-operator">=</span><span class="hljs-number">0</span><span class="hljs-comment">;</span><br>int i_redir<span class="hljs-operator">=</span><span class="hljs-number">0</span><span class="hljs-comment">;</span><br>int o_redir<span class="hljs-operator">=</span><span class="hljs-number">0</span><span class="hljs-comment">;</span><br>int _pipe<span class="hljs-operator">=</span><span class="hljs-number">0</span><span class="hljs-comment">;</span><br>int a_o_redir<span class="hljs-operator">=</span><span class="hljs-number">0</span><span class="hljs-comment">;</span><br>int pass<span class="hljs-operator">=</span><span class="hljs-number">0</span><span class="hljs-comment">;//命令解析的参数</span><br></code></pre></td></tr></table></figure><h5 id="code"><a href="#code" class="headerlink" title="code"></a>code</h5><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-type">int</span> <span class="hljs-title function_">analyze_cmd</span><span class="hljs-params">(<span class="hljs-type">int</span> argc,<span class="hljs-type">char</span>*argv[])</span>{<br> <span class="hljs-keyword">if</span> (argv[<span class="hljs-number">0</span>] == <span class="hljs-literal">NULL</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[<span class="hljs-number">0</span>], <span class="hljs-string">"cd"</span>) == <span class="hljs-number">0</span>) cd = <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">for</span> (<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < argc; i++){<br> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[i], <span class="hljs-string">">"</span>) == <span class="hljs-number">0</span>) o_redir = <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[i], <span class="hljs-string">"|"</span>) == <span class="hljs-number">0</span>) _pipe = <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[i], <span class="hljs-string">">>"</span>) == <span class="hljs-number">0</span>) a_o_redir = <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[i], <span class="hljs-string">"<"</span>) == <span class="hljs-number">0</span>) i_redir = <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[i], <span class="hljs-string">"&"</span>) == <span class="hljs-number">0</span>){<br> pass = <span class="hljs-number">1</span>;<br> argv[i]=<span class="hljs-literal">NULL</span>;<br> }<br> }<br>}<br></code></pre></td></tr></table></figure><p>每个参数都在do_cmd函数中辅助判定,从而使用不同的接口来实现命令。</p><h4 id="void-do-cmd-int-argc-char-argv"><a href="#void-do-cmd-int-argc-char-argv" class="headerlink" title="void do_cmd(int argc,char*argv[])"></a>void do_cmd(int argc,char*argv[])</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-type">void</span> <span class="hljs-title function_">do_cmd</span><span class="hljs-params">(<span class="hljs-type">int</span> argc,<span class="hljs-type">char</span>*argv[])</span>{<br> <span class="hljs-keyword">if</span>(pass==<span class="hljs-number">1</span>) argc--;<br> <span class="hljs-keyword">if</span> (cd == <span class="hljs-number">1</span>) mycd(argv);<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[<span class="hljs-number">0</span>], <span class="hljs-string">"history"</span>) == <span class="hljs-number">0</span>) showhistory();<span class="hljs-comment">//展示历史命令</span><br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[<span class="hljs-number">0</span>], <span class="hljs-string">"exit"</span>) == <span class="hljs-number">0</span>)<br> {<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"exit\n"</span>);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"有停止的任务\n"</span>);<br> <span class="hljs-built_in">exit</span>(<span class="hljs-number">0</span>);<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( i_redir== <span class="hljs-number">1</span>) iredir(argv);<span class="hljs-comment">// < </span><br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( o_redir== <span class="hljs-number">1</span>) oredir(argv);<span class="hljs-comment">// ></span><br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( a_o_redir== <span class="hljs-number">1</span>) aoredir(argv);<span class="hljs-comment">// >></span><br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( _pipe == <span class="hljs-number">1</span>) mymulpipe(argv, argc);<span class="hljs-comment">// | 管道放在最后判定,因为重定向中也有管道的判定</span><br> <span class="hljs-keyword">else</span> <span class="hljs-comment">//需要fork子进程进行执行的命令</span><br> {<br> <span class="hljs-keyword">if</span> (pid < <span class="hljs-number">0</span>)<br> {<br> perror(<span class="hljs-string">"fork"</span>);<br> <span class="hljs-built_in">exit</span>(<span class="hljs-number">1</span>);<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (pid == <span class="hljs-number">0</span>) <span class="hljs-comment">//子进程</span><br> {<br> execvp(argv[<span class="hljs-number">0</span>], argv);<br> perror(<span class="hljs-string">"command"</span>);<br> <span class="hljs-built_in">exit</span>(<span class="hljs-number">1</span>);<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (pid > <span class="hljs-number">0</span>) <span class="hljs-comment">//父进程</span><br> {<br> <span class="hljs-keyword">if</span>(pass==<span class="hljs-number">1</span>)<br> {<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%d\n"</span>,pid);<br> <span class="hljs-keyword">return</span>;<br> }<br> waitpid(pid, <span class="hljs-literal">NULL</span>, <span class="hljs-number">0</span>);<br> }<br> }<br>}<br></code></pre></td></tr></table></figure><p><strong>这个接口实际上通过判定参数真假值来调用其他函数来实现命令,本身只实现没有重定向和管道等的需要fork和execve的简单命令</strong></p><ul><li>这里只讲一下fork子进程实现的命令,其他在下面的具体接口再详解</li><li>fork返回两个pid值,一个是父进程的,一个是子进程的,fork后的代码会被父进程和子进程分别执行一遍,所以需要进行判定来分别编写父进程和子进程需要执行的代码</li><li>这里,子进程需要调用execvp来加载命令实现需要的代码</li><li>父进程则调用waitpid来监控子进程的进行,并且在有&的情况下将控制权重新交给主函数,从而让子进程在后台执行命令的同时不影响shell前台继续执行新命令</li></ul><h4 id="void-showhistory"><a href="#void-showhistory" class="headerlink" title="void showhistory()"></a>void showhistory()</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-type">void</span> <span class="hljs-title function_">showhistory</span><span class="hljs-params">()</span><br>{<br> <span class="hljs-type">int</span> i = <span class="hljs-number">0</span>;<br> HIST_ENTRY **his;<br> his = history_list();<br> <span class="hljs-keyword">while</span> (his[i] != <span class="hljs-literal">NULL</span>)<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%-3d %s\n"</span>, i, his[i++]->line);<br>}<br></code></pre></td></tr></table></figure><p>这里的HIST_ENTRY类型和history_list函数都在<readline/history.h>中有定义</p><h4 id="void-mycd-char-argv"><a href="#void-mycd-char-argv" class="headerlink" title="void mycd(char *argv[])"></a>void mycd(char *argv[])</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-type">char</span> lastpath[MAX];<span class="hljs-comment">//为实现cd-而声明</span><br><span class="hljs-type">void</span> <span class="hljs-title function_">mycd</span><span class="hljs-params">(<span class="hljs-type">char</span> *argv[])</span>{<br><span class="hljs-keyword">if</span> (argv[<span class="hljs-number">1</span>] == <span class="hljs-literal">NULL</span>)<span class="hljs-comment">//未输入要跳转的目录的情况</span><br> {<br> getcwd(lastpath, <span class="hljs-keyword">sizeof</span>(lastpath));<br> chdir(<span class="hljs-string">"/home"</span>);<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[<span class="hljs-number">1</span>], <span class="hljs-string">"-"</span>) == <span class="hljs-number">0</span>)<span class="hljs-comment">//实现cd -</span><br> {<br> <span class="hljs-type">char</span> newlastpath[MAX];<br> getcwd(newlastpath, <span class="hljs-keyword">sizeof</span>(lastpath));<br> chdir(lastpath);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%s\n"</span>, lastpath);<br> <span class="hljs-built_in">strcpy</span>(lastpath, newlastpath);<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[<span class="hljs-number">1</span>], <span class="hljs-string">"~"</span>) == <span class="hljs-number">0</span>)<span class="hljs-comment">//跳转主目录(这里的代码是跳转到我自己的主目录wanggang)</span><br> {<br> getcwd(lastpath, <span class="hljs-keyword">sizeof</span>(lastpath));<br> chdir(<span class="hljs-string">"/home/wanggang"</span>);<br> }<br> <span class="hljs-keyword">else</span><br> {<br> getcwd(lastpath, <span class="hljs-keyword">sizeof</span>(lastpath));<br> chdir(argv[<span class="hljs-number">1</span>]);<span class="hljs-comment">//跳转到输入的路径名</span><br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>为实现cd-,声明了lastpath来记录之前的路径</li><li>主要调用chdir来改变当前路径</li></ul><h4 id="void-oredir-char-argv"><a href="#void-oredir-char-argv" class="headerlink" title="void oredir(char *argv[])"></a>void oredir(char *argv[])</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-type">void</span> <span class="hljs-title function_">oredir</span><span class="hljs-params">(<span class="hljs-type">char</span> *argv[])</span>{<br><span class="hljs-type">char</span> *preargv[MAX] = {<span class="hljs-literal">NULL</span>};<br> <span class="hljs-type">int</span> i = <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">while</span> (<span class="hljs-built_in">strcmp</span>(argv[i], <span class="hljs-string">">"</span>))<br> {<br> preargv[i] = argv[i];<br> i++;<br> }<br> <span class="hljs-type">int</span> preargc=i;<span class="hljs-comment">//重定向前面参数的个数</span><br> i++;<br> <span class="hljs-type">int</span> fdout = dup(<span class="hljs-number">1</span>);<span class="hljs-comment">//让标准输出获取一个新的文件描述符</span><br> <span class="hljs-type">int</span> fd = open(argv[i], O_WRONLY | O_CREAT | O_TRUNC,<span class="hljs-number">0666</span>); <span class="hljs-comment">//只写模式|表示如果指定文件不存在,则创建这个文件|表示截断,如果文件存在,并且以只写、读写方式打开,则将其长度截断为0。</span><br> dup2(fd, <span class="hljs-number">1</span>);<br> <span class="hljs-type">pid_t</span> pid = fork();<br> <span class="hljs-keyword">if</span> (pid == <span class="hljs-number">0</span>) <span class="hljs-comment">//子进程</span><br> {<br> <span class="hljs-keyword">if</span> (_pipe=<span class="hljs-number">1</span>) <span class="hljs-comment">//管道'|'</span><br> {<br> mymulpipe(preargv, preargc);<br> }<br> <span class="hljs-keyword">else</span><br> execvp(preargv[<span class="hljs-number">0</span>], preargv);<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (pid > <span class="hljs-number">0</span>)<span class="hljs-comment">//父进程</span><br> {<br> <span class="hljs-keyword">if</span>(pass==<span class="hljs-number">1</span>)<br> {<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%d\n"</span>,pid);<br> <span class="hljs-keyword">return</span>;<br> }<br> waitpid(pid, <span class="hljs-literal">NULL</span>, <span class="hljs-number">0</span>);<br> }<br> dup2(fdout, <span class="hljs-number">1</span>);<br>}<br></code></pre></td></tr></table></figure><ul><li>定义preargv将重定向符之前的命令保存,并获得重定向符之后的文件描述符(没有该文件就创建一个)</li><li>fork子进程运行preargv里保存的命令</li><li>最后将获得的文件描述符重定向到标准输出</li></ul><h4 id="void-aoredir-char-argv"><a href="#void-aoredir-char-argv" class="headerlink" title="void aoredir(char *argv[])"></a>void aoredir(char *argv[])</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-type">void</span> <span class="hljs-title function_">aoredir</span><span class="hljs-params">(<span class="hljs-type">char</span> *argv[])</span>{<br><br> <span class="hljs-type">char</span> *preargv[MAX] = {<span class="hljs-literal">NULL</span>};<br> <span class="hljs-type">int</span> i = <span class="hljs-number">0</span>;<br> <br> <span class="hljs-keyword">while</span> (<span class="hljs-built_in">strcmp</span>(argv[i], <span class="hljs-string">">>"</span>))<br> {<br> preargv[i] = argv[i];<br> i++;<br> }<br> <span class="hljs-type">int</span> preargc=i;<span class="hljs-comment">//重定向前面参数的个数</span><br> i++;<br> <span class="hljs-type">int</span> fdout = dup(<span class="hljs-number">1</span>);<span class="hljs-comment">//让标准输出获取一个新的文件描述符</span><br> <span class="hljs-type">int</span> fd = open(argv[i], O_WRONLY | O_CREAT | O_APPEND,<span class="hljs-number">0666</span>); <span class="hljs-comment">//只写模式|表示如果指定文件不存在,则创建这个文件|表示追加,如果原来文件里面有内容,则这次写入会写在文件的最末尾。</span><br> <span class="hljs-type">pid_t</span> pid = fork();<br> dup2(fd, <span class="hljs-number">1</span>);<br> <span class="hljs-keyword">if</span> (pid == <span class="hljs-number">0</span>) <span class="hljs-comment">//子进程</span><br> {<br> <span class="hljs-keyword">if</span> (_pipe == <span class="hljs-number">1</span>) <span class="hljs-comment">//管道'|'</span><br> {<br> mymulpipe(preargv, preargc);<br> }<br> <span class="hljs-keyword">else</span><br> execvp(preargv[<span class="hljs-number">0</span>], preargv);<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (pid > <span class="hljs-number">0</span>)<br> {<br> <span class="hljs-keyword">if</span>(pass==<span class="hljs-number">1</span>)<br> {<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%d\n"</span>,pid);<br> <span class="hljs-keyword">return</span>;<br> }<br> waitpid(pid, <span class="hljs-literal">NULL</span>, <span class="hljs-number">0</span>);<br> }<br> dup2(fdout, <span class="hljs-number">1</span>);<br>}<br></code></pre></td></tr></table></figure><ul><li>基本和前面的oredir(output redirect的缩写)函数一样,区别在于调用open时使用的参数不同</li></ul><h4 id="void-iredir-char-argv"><a href="#void-iredir-char-argv" class="headerlink" title="void iredir(char *argv[])"></a>void iredir(char *argv[])</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-type">void</span> <span class="hljs-title function_">iredir</span><span class="hljs-params">(<span class="hljs-type">char</span> *argv[])</span>{<br><span class="hljs-type">char</span> *preargv[MAX] = {<span class="hljs-literal">NULL</span>};<br> <span class="hljs-type">int</span> i = <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">while</span> (<span class="hljs-built_in">strcmp</span>(argv[i], <span class="hljs-string">"<"</span>))<br> {<br> preargv[i] = argv[i];<br> i++;<br> }<br> i++;<br> <span class="hljs-type">int</span> preargc=i;<span class="hljs-comment">//重定向前面参数的个数</span><br> <span class="hljs-type">int</span> fdin = dup(<span class="hljs-number">0</span>);<span class="hljs-comment">//让标准输入获取一个新的文件描述符</span><br> <span class="hljs-type">int</span> fd = open(argv[i], O_RDONLY,<span class="hljs-number">0666</span>); <span class="hljs-comment">//只读模式</span><br> dup2(fd, <span class="hljs-number">0</span>);<br> <span class="hljs-type">pid_t</span> pid = fork();<br> <span class="hljs-keyword">if</span> (pid == <span class="hljs-number">0</span>) <span class="hljs-comment">//子进程</span><br> {<br> <span class="hljs-keyword">if</span> (_pipe == <span class="hljs-number">1</span>) <span class="hljs-comment">//管道'|'</span><br> {<br> mymulpipe(preargv, preargc);<br> }<br> <span class="hljs-keyword">else</span><br> execvp(preargv[<span class="hljs-number">0</span>], preargv);<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (pid > <span class="hljs-number">0</span>)<br> {<br> waitpid(pid, <span class="hljs-literal">NULL</span>, <span class="hljs-number">0</span>);<br> }<br> dup2(fdin, <span class="hljs-number">0</span>);<br>}<br></code></pre></td></tr></table></figure><ul><li>代码思路和前面的标准输出重定向基本相同,不同在于使用的文件描述符不同</li></ul><h4 id="void-mymulpipe-char-argv-int-argc"><a href="#void-mymulpipe-char-argv-int-argc" class="headerlink" title="void mymulpipe(char *argv[], int argc )"></a>void mymulpipe(char *argv[], int argc )</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-type">void</span> <span class="hljs-title function_">mymulpipe</span><span class="hljs-params">(<span class="hljs-type">char</span> *argv[], <span class="hljs-type">int</span> argc )</span>{<br><span class="hljs-type">pid_t</span> pid;<br> <span class="hljs-type">int</span> index[<span class="hljs-number">10</span>];<span class="hljs-comment">//存放每个管道的下标</span><br> <span class="hljs-type">int</span> number=<span class="hljs-number">0</span>;<span class="hljs-comment">//统计管道个数</span><br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i=<span class="hljs-number">0</span>;i<argc;i++)<br> <span class="hljs-keyword">if</span>(!<span class="hljs-built_in">strcmp</span>(argv[i],<span class="hljs-string">"|"</span>)) index[number++]=i;<br> <span class="hljs-type">int</span> cmdcount=number+<span class="hljs-number">1</span>;<span class="hljs-comment">//命令个数</span><br> <span class="hljs-type">char</span>* cmd[cmdcount][<span class="hljs-number">10</span>];<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i=<span class="hljs-number">0</span>;i<cmdcount;i++)<span class="hljs-comment">//将命令以管道分割存放组数组里</span><br> {<br> <span class="hljs-keyword">if</span>(i==<span class="hljs-number">0</span>)<br> {<br> <span class="hljs-type">int</span> n=<span class="hljs-number">0</span>;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j=<span class="hljs-number">0</span>;j<index[i];j++)<br> {<br> cmd[i][n++]=argv[j];<br> }<br> cmd[i][n]=<span class="hljs-literal">NULL</span>;<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(i==number)<br> {<br> <span class="hljs-type">int</span> n=<span class="hljs-number">0</span>;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j=index[i<span class="hljs-number">-1</span>]+<span class="hljs-number">1</span>;j<argc;j++)<br> {<br> cmd[i][n++]=argv[j];<br> }<br> cmd[i][n]=<span class="hljs-literal">NULL</span>;<br> }<br> <span class="hljs-keyword">else</span> <br> {<br> <span class="hljs-type">int</span> n=<span class="hljs-number">0</span>;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j=index[i<span class="hljs-number">-1</span>]+<span class="hljs-number">1</span>;j<index[i];j++)<br> {<br> cmd[i][n++]=argv[j];<br> }<br> cmd[i][n]=<span class="hljs-literal">NULL</span>;<br> }<br> }<span class="hljs-comment">//命令已经分割好了,下面可以创建管道了。</span><br> <span class="hljs-type">int</span> fd[number][<span class="hljs-number">2</span>]; <span class="hljs-comment">//存放管道的描述符</span><br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i=<span class="hljs-number">0</span>;i<number;i++)<span class="hljs-comment">//循环创建多个管道</span><br> {<br> pipe(fd[i]);<br> }<br> <span class="hljs-type">int</span> i=<span class="hljs-number">0</span>;<br> <span class="hljs-keyword">for</span>(i=<span class="hljs-number">0</span>;i<cmdcount;i++)<span class="hljs-comment">//父进程循环创建多个并列子进程</span><br> {<br> pid=fork();<br> <span class="hljs-keyword">if</span>(pid==<span class="hljs-number">0</span>)<span class="hljs-comment">//子进程退出,防止创建过多进程</span><br> <span class="hljs-keyword">break</span>;<br> }<br> <span class="hljs-keyword">if</span>(pid==<span class="hljs-number">0</span>)<span class="hljs-comment">//子进程</span><br> {<br> <span class="hljs-keyword">if</span>(number)<br> {<br> <span class="hljs-keyword">if</span>(i==<span class="hljs-number">0</span>)<span class="hljs-comment">//第一个子进程</span><br> {<br> dup2(fd[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>],<span class="hljs-number">1</span>);<span class="hljs-comment">//绑定写端` </span><br> close(fd[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>]);<span class="hljs-comment">//关闭读端</span><br> <span class="hljs-comment">//其他进程读写端全部关闭</span><br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j=<span class="hljs-number">1</span>;j<number;j++)<br> {<br> close(fd[j][<span class="hljs-number">1</span>]);<br> close(fd[j][<span class="hljs-number">0</span>]);<br> }<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(i==number)<span class="hljs-comment">//最后一个子进程</span><br> {<br> dup2(fd[i<span class="hljs-number">-1</span>][<span class="hljs-number">0</span>],<span class="hljs-number">0</span>);<span class="hljs-comment">//打开读端</span><br> close(fd[i<span class="hljs-number">-1</span>][<span class="hljs-number">1</span>]);<span class="hljs-comment">//关闭写端</span><br> <span class="hljs-comment">//其他进程读写端全部关闭</span><br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j=<span class="hljs-number">0</span>;j<number<span class="hljs-number">-1</span>;j++)<br> {<br> close(fd[j][<span class="hljs-number">1</span>]);<br> close(fd[j][<span class="hljs-number">0</span>]);<br> }<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-comment">//中间进程</span><br> {<br> dup2(fd[i<span class="hljs-number">-1</span>][<span class="hljs-number">0</span>],<span class="hljs-number">0</span>);<span class="hljs-comment">//前一个管道的读端打开</span><br> close(fd[i<span class="hljs-number">-1</span>][<span class="hljs-number">1</span>]);<span class="hljs-comment">//前一个写端关闭</span><br> dup2(fd[i][<span class="hljs-number">1</span>],<span class="hljs-number">1</span>);<span class="hljs-comment">//后一个管道的写端打开</span><br> close(fd[i][<span class="hljs-number">0</span>]);<span class="hljs-comment">//后一个读端关闭</span><br> <span class="hljs-comment">//其他的全部关闭</span><br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j=<span class="hljs-number">0</span>;j<number;j++)<br> {<br> <span class="hljs-keyword">if</span>(j!=i&&j!=(i<span class="hljs-number">-1</span>))<br> {<br> close(fd[j][<span class="hljs-number">0</span>]);<br> close(fd[j][<span class="hljs-number">1</span>]);<br> }<br> }<br> }<br> }<br> <br> execvp(cmd[i][<span class="hljs-number">0</span>],cmd[i]);<span class="hljs-comment">//执行命令</span><br> perror(<span class="hljs-string">"execvp"</span>);<br> <span class="hljs-built_in">exit</span>(<span class="hljs-number">1</span>);<br> }<br> <span class="hljs-keyword">else</span>{<span class="hljs-comment">//父进程</span><br> <span class="hljs-keyword">for</span>(i=<span class="hljs-number">0</span>;i<number;i++)<br> {<br> close(fd[i][<span class="hljs-number">0</span>]);<br> close(fd[i][<span class="hljs-number">1</span>]);<span class="hljs-comment">//父进程端口全部关掉</span><br><br> }<br> <span class="hljs-keyword">if</span>(pass==<span class="hljs-number">1</span>)<br> {<br> pass=<span class="hljs-number">0</span>;<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%d\n"</span>,pid);<br> <span class="hljs-keyword">return</span>;<br> }<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j=<span class="hljs-number">0</span>;j<cmdcount;j++)<span class="hljs-comment">//父进程等待子进程</span><br> wait(<span class="hljs-literal">NULL</span>);<br>}<br></code></pre></td></tr></table></figure><ul><li>关于管道是什么,<a href="https://blog.csdn.net/oguro/article/details/53841949?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171126754816800182763665%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=171126754816800182763665&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-53841949-null-null.142%5Ev99%5Epc_search_result_base6&utm_term=%E7%AE%A1%E9%81%93&spm=1018.2226.3001.4187">可以点击这里</a>。</li><li>这里分两大步,第一步是通过一个二维数组将各个管道两端的命令分隔开</li><li>第二步是fork出相应数量的进程并创建相应数量的管道来执行命令</li></ul><h4 id="全部代码"><a href="#全部代码" class="headerlink" title="全部代码"></a>全部代码</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><stdio.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><string.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><sys/wait.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><sys/types.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><sys/stat.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><stdlib.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><unistd.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><fcntl.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><dirent.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><readline/readline.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><readline/history.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><errno.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> PATHMAX 4096</span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> MAX 200</span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> BLUE <span class="hljs-string">"\033[34m"</span><span class="hljs-comment">//宏定义实现有色字体</span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> GREEN <span class="hljs-string">"\033[32m"</span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> CLOSE <span class="hljs-string">"\033[0m"</span></span><br><br><span class="hljs-type">int</span> cd =<span class="hljs-number">0</span>;<br><span class="hljs-type">int</span> i_redir=<span class="hljs-number">0</span>;<br><span class="hljs-type">int</span> o_redir=<span class="hljs-number">0</span>;<br><span class="hljs-type">int</span> _pipe=<span class="hljs-number">0</span>;<br><span class="hljs-type">int</span> a_o_redir=<span class="hljs-number">0</span>;<br><span class="hljs-type">int</span> pass=<span class="hljs-number">0</span>;<span class="hljs-comment">//命令解析的参数</span><br><br><span class="hljs-type">void</span> <span class="hljs-title function_">printname</span><span class="hljs-params">(<span class="hljs-type">void</span>)</span>;<br><span class="hljs-type">int</span> <span class="hljs-title function_">analyze_cmd</span><span class="hljs-params">(<span class="hljs-type">int</span>,<span class="hljs-type">char</span>**)</span>;<br><span class="hljs-type">void</span> <span class="hljs-title function_">showhistory</span><span class="hljs-params">()</span>;<br><span class="hljs-type">void</span> <span class="hljs-title function_">mycd</span><span class="hljs-params">(<span class="hljs-type">char</span> *argv[])</span>;<br><span class="hljs-type">void</span> <span class="hljs-title function_">oredir</span><span class="hljs-params">(<span class="hljs-type">char</span> *argv[])</span>;<br><span class="hljs-type">void</span> <span class="hljs-title function_">aoredir</span><span class="hljs-params">(<span class="hljs-type">char</span> *argv[])</span>;<br><span class="hljs-type">void</span> <span class="hljs-title function_">iredir</span><span class="hljs-params">(<span class="hljs-type">char</span> *argv[])</span>;<br><span class="hljs-type">void</span> <span class="hljs-title function_">mymulpipe</span><span class="hljs-params">(<span class="hljs-type">char</span> *argv[], <span class="hljs-type">int</span> )</span>;<br><span class="hljs-type">void</span> <span class="hljs-title function_">do_cmd</span><span class="hljs-params">(<span class="hljs-type">int</span>,<span class="hljs-type">char</span>**)</span>;<br><span class="hljs-type">void</span> <span class="hljs-title function_">clear_para</span><span class="hljs-params">()</span>;<br><br><span class="hljs-type">int</span> <span class="hljs-title function_">main</span><span class="hljs-params">()</span>{<br> read_history(<span class="hljs-literal">NULL</span>);<br> signal(SIGINT,SIG_IGN);<span class="hljs-comment">//屏蔽ctrl+c</span><br> signal(SIGTSTP,SIG_IGN); <span class="hljs-comment">//屏蔽ctrl+z</span><br> <span class="hljs-keyword">while</span>(<span class="hljs-number">1</span>){<br> <span class="hljs-type">char</span>*argv[MAX]={<span class="hljs-literal">NULL</span>};<br> printname();<br> <span class="hljs-type">char</span>*command=readline(<span class="hljs-string">" "</span>);<span class="hljs-comment">//readline函数输出给出的字符串并读取一行输入,并为读取的输入动态分配内存,返回值为指向读取输入的指针</span><br> <span class="hljs-keyword">if</span> (command == <span class="hljs-literal">NULL</span>) {<span class="hljs-built_in">printf</span>(<span class="hljs-string">"\n"</span>);<span class="hljs-keyword">continue</span>;}<span class="hljs-comment">//屏蔽ctrl+d </span><br> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strlen</span>(command) == <span class="hljs-number">0</span>) <span class="hljs-keyword">continue</span>;<span class="hljs-comment">//回车不爆栈</span><br> <span class="hljs-type">int</span> argc=<span class="hljs-number">1</span>; <br> argv[<span class="hljs-number">0</span>] = strtok(command, <span class="hljs-string">" "</span>);<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i=<span class="hljs-number">1</span>;argv[i] = strtok(<span class="hljs-literal">NULL</span>, <span class="hljs-string">" "</span>);i++) argc++;<span class="hljs-comment">//将命令行输入分割为多个命令</span><br> analyze_cmd(argc,argv);<span class="hljs-comment">//解析命令</span><br> do_cmd(argc,argv);<span class="hljs-comment">//实现命令</span><br> <span class="hljs-built_in">free</span>(command); <span class="hljs-comment">//释放空间</span><br> clear_para();<span class="hljs-comment">//重置参数</span><br> }<br>}<br><br><span class="hljs-type">void</span> <span class="hljs-title function_">printname</span><span class="hljs-params">()</span>{<br> <span class="hljs-type">char</span> pathname[PATHMAX];<br> getcwd(pathname,PATHMAX);<span class="hljs-comment">//获取当前目录</span><br> <span class="hljs-built_in">printf</span>(BLUE<span class="hljs-string">"Whosefrienda-shell"</span>CLOSE);<span class="hljs-comment">//打印shell名称</span><br> <span class="hljs-built_in">printf</span>(GREEN<span class="hljs-string">" :%s"</span>CLOSE,pathname);<span class="hljs-comment">//打印路径</span><br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"$ "</span>);<br> fflush(<span class="hljs-built_in">stdout</span>);<span class="hljs-comment">//清除缓冲区</span><br>}<br><br><span class="hljs-type">int</span> <span class="hljs-title function_">analyze_cmd</span><span class="hljs-params">(<span class="hljs-type">int</span> argc,<span class="hljs-type">char</span>*argv[])</span>{<br> <span class="hljs-keyword">if</span> (argv[<span class="hljs-number">0</span>] == <span class="hljs-literal">NULL</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[<span class="hljs-number">0</span>], <span class="hljs-string">"cd"</span>) == <span class="hljs-number">0</span>) cd = <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">for</span> (<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < argc; i++){<br> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[i], <span class="hljs-string">">"</span>) == <span class="hljs-number">0</span>) o_redir = <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[i], <span class="hljs-string">"|"</span>) == <span class="hljs-number">0</span>) _pipe = <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[i], <span class="hljs-string">">>"</span>) == <span class="hljs-number">0</span>) a_o_redir = <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[i], <span class="hljs-string">"<"</span>) == <span class="hljs-number">0</span>) i_redir = <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[i], <span class="hljs-string">"&"</span>) == <span class="hljs-number">0</span>){<br> pass = <span class="hljs-number">1</span>;<br> argv[i]=<span class="hljs-literal">NULL</span>;<br> }<br> }<br>}<br><br><span class="hljs-type">void</span> <span class="hljs-title function_">do_cmd</span><span class="hljs-params">(<span class="hljs-type">int</span> argc,<span class="hljs-type">char</span>*argv[])</span>{<br> <span class="hljs-keyword">if</span>(pass==<span class="hljs-number">1</span>) argc--;<br> <span class="hljs-keyword">if</span> (cd == <span class="hljs-number">1</span>) mycd(argv);<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[<span class="hljs-number">0</span>], <span class="hljs-string">"history"</span>) == <span class="hljs-number">0</span>) showhistory();<span class="hljs-comment">//展示历史命令</span><br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[<span class="hljs-number">0</span>], <span class="hljs-string">"exit"</span>) == <span class="hljs-number">0</span>)<br> {<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"exit\n"</span>);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"有停止的任务\n"</span>);<br> <span class="hljs-built_in">exit</span>(<span class="hljs-number">0</span>);<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( i_redir== <span class="hljs-number">1</span>) iredir(argv);<span class="hljs-comment">// < </span><br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( o_redir== <span class="hljs-number">1</span>) oredir(argv);<span class="hljs-comment">// ></span><br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( a_o_redir== <span class="hljs-number">1</span>) aoredir(argv);<span class="hljs-comment">// >></span><br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( _pipe == <span class="hljs-number">1</span>) mymulpipe(argv, argc);<span class="hljs-comment">// | 管道放在最后判定,因为重定向中也有管道的判定</span><br> <span class="hljs-keyword">else</span> <span class="hljs-comment">//需要fork子进程进行执行的命令</span><br> {<br> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[<span class="hljs-number">0</span>], <span class="hljs-string">"ls"</span>) == <span class="hljs-number">0</span>)<br> argv[argc++] = <span class="hljs-string">"--color=auto"</span>;<br> <span class="hljs-type">pid_t</span> pid = fork();<br> <span class="hljs-keyword">if</span> (pid < <span class="hljs-number">0</span>)<br> {<br> perror(<span class="hljs-string">"fork"</span>);<br> <span class="hljs-built_in">exit</span>(<span class="hljs-number">1</span>);<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (pid == <span class="hljs-number">0</span>) <span class="hljs-comment">//子进程</span><br> {<br> execvp(argv[<span class="hljs-number">0</span>], argv);<br> perror(<span class="hljs-string">"command"</span>);<br> <span class="hljs-built_in">exit</span>(<span class="hljs-number">1</span>);<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (pid > <span class="hljs-number">0</span>) <span class="hljs-comment">//父进程</span><br> {<br> <span class="hljs-keyword">if</span>(pass==<span class="hljs-number">1</span>)<br> {<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%d\n"</span>,pid);<br> <span class="hljs-keyword">return</span>;<br> }<br> waitpid(pid, <span class="hljs-literal">NULL</span>, <span class="hljs-number">0</span>);<br> }<br> }<br>}<br><br><span class="hljs-type">void</span> <span class="hljs-title function_">showhistory</span><span class="hljs-params">()</span><br>{<br> <span class="hljs-type">int</span> i = <span class="hljs-number">0</span>;<br> HIST_ENTRY **his;<br> his = history_list();<br> <span class="hljs-keyword">while</span> (his[i] != <span class="hljs-literal">NULL</span>)<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%-3d %s\n"</span>, i, his[i++]->line);<br>}<br><br><span class="hljs-type">char</span> lastpath[MAX];<span class="hljs-comment">//为实现cd-而声明</span><br><span class="hljs-type">void</span> <span class="hljs-title function_">mycd</span><span class="hljs-params">(<span class="hljs-type">char</span> *argv[])</span>{<br><span class="hljs-keyword">if</span> (argv[<span class="hljs-number">1</span>] == <span class="hljs-literal">NULL</span>)<span class="hljs-comment">//未输入要跳转的目录的情况</span><br> {<br> getcwd(lastpath, <span class="hljs-keyword">sizeof</span>(lastpath));<br> chdir(<span class="hljs-string">"/home"</span>);<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[<span class="hljs-number">1</span>], <span class="hljs-string">"-"</span>) == <span class="hljs-number">0</span>)<span class="hljs-comment">//实现cd -</span><br> {<br> <span class="hljs-type">char</span> newlastpath[MAX];<br> getcwd(newlastpath, <span class="hljs-keyword">sizeof</span>(lastpath));<br> chdir(lastpath);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%s\n"</span>, lastpath);<br> <span class="hljs-built_in">strcpy</span>(lastpath, newlastpath);<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">strcmp</span>(argv[<span class="hljs-number">1</span>], <span class="hljs-string">"~"</span>) == <span class="hljs-number">0</span>)<span class="hljs-comment">//跳转主目录(这里的代码是跳转到我自己的主目录wanggang)</span><br> {<br> getcwd(lastpath, <span class="hljs-keyword">sizeof</span>(lastpath));<br> chdir(<span class="hljs-string">"/home/wanggang"</span>);<br> }<br> <span class="hljs-keyword">else</span><br> {<br> getcwd(lastpath, <span class="hljs-keyword">sizeof</span>(lastpath));<br> chdir(argv[<span class="hljs-number">1</span>]);<br> }<br>}<br><br><span class="hljs-type">void</span> <span class="hljs-title function_">oredir</span><span class="hljs-params">(<span class="hljs-type">char</span> *argv[])</span>{<br><span class="hljs-type">char</span> *preargv[MAX] = {<span class="hljs-literal">NULL</span>};<br> <span class="hljs-type">int</span> i = <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">while</span> (<span class="hljs-built_in">strcmp</span>(argv[i], <span class="hljs-string">">"</span>))<br> {<br> preargv[i] = argv[i];<br> i++;<br> }<br> <span class="hljs-type">int</span> preargc=i;<span class="hljs-comment">//重定向前面参数的个数</span><br> i++;<br> <span class="hljs-comment">//出现 echo "adcbe" > test.c 这种情况</span><br> <span class="hljs-type">int</span> fdout = dup(<span class="hljs-number">1</span>);<span class="hljs-comment">//让标准输出获取一个新的文件描述符</span><br> <span class="hljs-type">int</span> fd = open(argv[i], O_WRONLY | O_CREAT | O_TRUNC,<span class="hljs-number">0666</span>); <span class="hljs-comment">//只写模式|表示如果指定文件不存在,则创建这个文件|表示截断,如果文件存在,并且以只写、读写方式打开,则将其长度截断为0。</span><br> dup2(fd, <span class="hljs-number">1</span>);<br> <span class="hljs-type">pid_t</span> pid = fork();<br> <span class="hljs-keyword">if</span> (pid == <span class="hljs-number">0</span>) <span class="hljs-comment">//子进程</span><br> {<br> <span class="hljs-keyword">if</span> (_pipe=<span class="hljs-number">1</span>) <span class="hljs-comment">//管道'|'</span><br> {<br> mymulpipe(preargv, preargc);<br> }<br> <span class="hljs-keyword">else</span><br> execvp(preargv[<span class="hljs-number">0</span>], preargv);<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (pid > <span class="hljs-number">0</span>)<span class="hljs-comment">//父进程</span><br> {<br> <span class="hljs-keyword">if</span>(pass==<span class="hljs-number">1</span>)<br> {<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%d\n"</span>,pid);<br> <span class="hljs-keyword">return</span>;<br> }<br> waitpid(pid, <span class="hljs-literal">NULL</span>, <span class="hljs-number">0</span>);<br> }<br> dup2(fdout, <span class="hljs-number">1</span>);<span class="hljs-comment">//</span><br>}<br><br><span class="hljs-type">void</span> <span class="hljs-title function_">aoredir</span><span class="hljs-params">(<span class="hljs-type">char</span> *argv[])</span>{<br><br> <span class="hljs-type">char</span> *preargv[MAX] = {<span class="hljs-literal">NULL</span>};<br> <span class="hljs-type">int</span> i = <span class="hljs-number">0</span>;<br> <br> <span class="hljs-keyword">while</span> (<span class="hljs-built_in">strcmp</span>(argv[i], <span class="hljs-string">">>"</span>))<br> {<br> preargv[i] = argv[i];<br> i++;<br> }<br> <span class="hljs-type">int</span> preargc=i;<span class="hljs-comment">//重定向前面参数的个数</span><br> i++;<br> <span class="hljs-type">int</span> fdout = dup(<span class="hljs-number">1</span>);<span class="hljs-comment">//让标准输出获取一个新的文件描述符</span><br> <span class="hljs-type">int</span> fd = open(argv[i], O_WRONLY | O_CREAT | O_APPEND,<span class="hljs-number">0666</span>); <span class="hljs-comment">//只写模式|表示如果指定文件不存在,则创建这个文件|表示追加,如果原来文件里面有内容,则这次写入会写在文件的最末尾。</span><br> <span class="hljs-type">pid_t</span> pid = fork();<br> dup2(fd, <span class="hljs-number">1</span>);<br> <span class="hljs-keyword">if</span> (pid == <span class="hljs-number">0</span>) <span class="hljs-comment">//子进程</span><br> {<br> <span class="hljs-keyword">if</span> (_pipe == <span class="hljs-number">1</span>) <span class="hljs-comment">//管道'|'</span><br> {<br> mymulpipe(preargv, preargc);<br> }<br> <span class="hljs-keyword">else</span><br> execvp(preargv[<span class="hljs-number">0</span>], preargv);<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (pid > <span class="hljs-number">0</span>)<br> {<br> <span class="hljs-keyword">if</span>(pass==<span class="hljs-number">1</span>)<br> {<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%d\n"</span>,pid);<br> <span class="hljs-keyword">return</span>;<br> }<br> waitpid(pid, <span class="hljs-literal">NULL</span>, <span class="hljs-number">0</span>);<br> }<br> dup2(fdout, <span class="hljs-number">1</span>);<br>}<br><br><span class="hljs-type">void</span> <span class="hljs-title function_">iredir</span><span class="hljs-params">(<span class="hljs-type">char</span> *argv[])</span>{<br><span class="hljs-type">char</span> *preargv[MAX] = {<span class="hljs-literal">NULL</span>};<br> <span class="hljs-type">int</span> i = <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">while</span> (<span class="hljs-built_in">strcmp</span>(argv[i], <span class="hljs-string">"<"</span>))<br> {<br> preargv[i] = argv[i];<br> i++;<br> }<br> i++;<br> <span class="hljs-type">int</span> preargc=i;<span class="hljs-comment">//重定向前面参数的个数</span><br> <span class="hljs-type">int</span> fdin = dup(<span class="hljs-number">0</span>);<span class="hljs-comment">//让标准输入获取一个新的文件描述符</span><br> <span class="hljs-type">int</span> fd = open(argv[i], O_RDONLY,<span class="hljs-number">0666</span>); <span class="hljs-comment">//只读模式</span><br> dup2(fd, <span class="hljs-number">0</span>);<br> <span class="hljs-type">pid_t</span> pid = fork();<br> <span class="hljs-keyword">if</span> (pid == <span class="hljs-number">0</span>) <span class="hljs-comment">//子进程</span><br> {<br> <span class="hljs-keyword">if</span> (_pipe == <span class="hljs-number">1</span>) <span class="hljs-comment">//管道'|'</span><br> {<br> mymulpipe(preargv, preargc);<br> }<br> <span class="hljs-keyword">else</span><br> execvp(preargv[<span class="hljs-number">0</span>], preargv);<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (pid > <span class="hljs-number">0</span>)<br> {<br> waitpid(pid, <span class="hljs-literal">NULL</span>, <span class="hljs-number">0</span>);<br> }<br> dup2(fdin, <span class="hljs-number">0</span>);<br>}<br><br><span class="hljs-type">void</span> <span class="hljs-title function_">mymulpipe</span><span class="hljs-params">(<span class="hljs-type">char</span> *argv[], <span class="hljs-type">int</span> argc )</span>{<br><span class="hljs-type">pid_t</span> pid;<br> <span class="hljs-type">int</span> index[<span class="hljs-number">10</span>];<span class="hljs-comment">//存放每个管道的下标</span><br> <span class="hljs-type">int</span> number=<span class="hljs-number">0</span>;<span class="hljs-comment">//统计管道个数</span><br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i=<span class="hljs-number">0</span>;i<argc;i++)<br> <span class="hljs-keyword">if</span>(!<span class="hljs-built_in">strcmp</span>(argv[i],<span class="hljs-string">"|"</span>)) index[number++]=i;<br> <span class="hljs-type">int</span> cmdcount=number+<span class="hljs-number">1</span>;<span class="hljs-comment">//命令个数</span><br> <span class="hljs-type">char</span>* cmd[cmdcount][<span class="hljs-number">10</span>];<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i=<span class="hljs-number">0</span>;i<cmdcount;i++)<span class="hljs-comment">//将命令以管道分割存放组数组里</span><br> {<br> <span class="hljs-keyword">if</span>(i==<span class="hljs-number">0</span>)<br> {<br> <span class="hljs-type">int</span> n=<span class="hljs-number">0</span>;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j=<span class="hljs-number">0</span>;j<index[i];j++)<br> {<br> cmd[i][n++]=argv[j];<br> }<br> cmd[i][n]=<span class="hljs-literal">NULL</span>;<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(i==number)<br> {<br> <span class="hljs-type">int</span> n=<span class="hljs-number">0</span>;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j=index[i<span class="hljs-number">-1</span>]+<span class="hljs-number">1</span>;j<argc;j++)<br> {<br> cmd[i][n++]=argv[j];<br> }<br> cmd[i][n]=<span class="hljs-literal">NULL</span>;<br> }<br> <span class="hljs-keyword">else</span> <br> {<br> <span class="hljs-type">int</span> n=<span class="hljs-number">0</span>;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j=index[i<span class="hljs-number">-1</span>]+<span class="hljs-number">1</span>;j<index[i];j++)<br> {<br> cmd[i][n++]=argv[j];<br> }<br> cmd[i][n]=<span class="hljs-literal">NULL</span>;<br> }<br> }<span class="hljs-comment">//命令已经分割好了,下面可以创建管道了。</span><br> <span class="hljs-type">int</span> fd[number][<span class="hljs-number">2</span>]; <span class="hljs-comment">//存放管道的描述符</span><br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i=<span class="hljs-number">0</span>;i<number;i++)<span class="hljs-comment">//循环创建多个管道</span><br> {<br> pipe(fd[i]);<br> }<br> <span class="hljs-type">int</span> i=<span class="hljs-number">0</span>;<br> <span class="hljs-keyword">for</span>(i=<span class="hljs-number">0</span>;i<cmdcount;i++)<span class="hljs-comment">//父进程循环创建多个并列子进程</span><br> {<br> pid=fork();<br> <span class="hljs-keyword">if</span>(pid==<span class="hljs-number">0</span>)<span class="hljs-comment">//子进程退出,防止创建过多进程</span><br> <span class="hljs-keyword">break</span>;<br> }<br> <span class="hljs-keyword">if</span>(pid==<span class="hljs-number">0</span>)<span class="hljs-comment">//子进程</span><br> {<br> <span class="hljs-keyword">if</span>(number)<br> {<br> <span class="hljs-keyword">if</span>(i==<span class="hljs-number">0</span>)<span class="hljs-comment">//第一个子进程</span><br> {<br> dup2(fd[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>],<span class="hljs-number">1</span>);<span class="hljs-comment">//绑定写端` </span><br> close(fd[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>]);<span class="hljs-comment">//关闭读端</span><br> <span class="hljs-comment">//其他进程读写端全部关闭</span><br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j=<span class="hljs-number">1</span>;j<number;j++)<br> {<br> close(fd[j][<span class="hljs-number">1</span>]);<br> close(fd[j][<span class="hljs-number">0</span>]);<br> }<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(i==number)<span class="hljs-comment">//最后一个子进程</span><br> {<br> dup2(fd[i<span class="hljs-number">-1</span>][<span class="hljs-number">0</span>],<span class="hljs-number">0</span>);<span class="hljs-comment">//打开读端</span><br> close(fd[i<span class="hljs-number">-1</span>][<span class="hljs-number">1</span>]);<span class="hljs-comment">//关闭写端</span><br> <span class="hljs-comment">//其他进程读写端全部关闭</span><br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j=<span class="hljs-number">0</span>;j<number<span class="hljs-number">-1</span>;j++)<br> {<br> close(fd[j][<span class="hljs-number">1</span>]);<br> close(fd[j][<span class="hljs-number">0</span>]);<br> }<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-comment">//中间进程</span><br> {<br> dup2(fd[i<span class="hljs-number">-1</span>][<span class="hljs-number">0</span>],<span class="hljs-number">0</span>);<span class="hljs-comment">//前一个管道的读端打开</span><br> close(fd[i<span class="hljs-number">-1</span>][<span class="hljs-number">1</span>]);<span class="hljs-comment">//前一个写端关闭</span><br> dup2(fd[i][<span class="hljs-number">1</span>],<span class="hljs-number">1</span>);<span class="hljs-comment">//后一个管道的写端打开</span><br> close(fd[i][<span class="hljs-number">0</span>]);<span class="hljs-comment">//后一个读端关闭</span><br> <span class="hljs-comment">//其他的全部关闭</span><br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j=<span class="hljs-number">0</span>;j<number;j++)<br> {<br> <span class="hljs-keyword">if</span>(j!=i&&j!=(i<span class="hljs-number">-1</span>))<br> {<br> close(fd[j][<span class="hljs-number">0</span>]);<br> close(fd[j][<span class="hljs-number">1</span>]);<br> }<br> }<br> }<br> }<br> <br> execvp(cmd[i][<span class="hljs-number">0</span>],cmd[i]);<span class="hljs-comment">//执行命令</span><br> perror(<span class="hljs-string">"execvp"</span>);<br> <span class="hljs-built_in">exit</span>(<span class="hljs-number">1</span>);<br> }<br> <span class="hljs-keyword">else</span>{<span class="hljs-comment">//父进程</span><br> <span class="hljs-keyword">for</span>(i=<span class="hljs-number">0</span>;i<number;i++)<br> {<br> close(fd[i][<span class="hljs-number">0</span>]);<br> close(fd[i][<span class="hljs-number">1</span>]);<span class="hljs-comment">//父进程端口全部关掉</span><br><br> }<br> <span class="hljs-keyword">if</span>(pass==<span class="hljs-number">1</span>)<br> {<br> pass=<span class="hljs-number">0</span>;<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%d\n"</span>,pid);<br> <span class="hljs-keyword">return</span>;<br> }<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j=<span class="hljs-number">0</span>;j<cmdcount;j++)<span class="hljs-comment">//父进程等待子进程</span><br> wait(<span class="hljs-literal">NULL</span>);<br>}<br>}<br><span class="hljs-type">void</span> <span class="hljs-title function_">clear_para</span><span class="hljs-params">()</span>{<br>cd =<span class="hljs-number">0</span>;<br>i_redir=<span class="hljs-number">0</span>;<br>o_redir=<span class="hljs-number">0</span>;<br>_pipe=<span class="hljs-number">0</span>;<br>a_o_redir=<span class="hljs-number">0</span>;<br>}<br><br></code></pre></td></tr></table></figure><h4 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h4><p>1.《Linux/Unix系统编程手册》</p><p>2.学长的shell</p>]]></content>
</entry>
</search>