<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>鬼の领地 &#187; ujudger</title>
	<atom:link href="http://blog.upsuper.org/tag/ujudger/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.upsuper.org</link>
	<description>the place where there are some ghost appearing...</description>
	<lastBuildDate>Wed, 19 Oct 2011 13:21:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>ujudger 0.1 发布</title>
		<link>http://blog.upsuper.org/ujudger-0-1-release/</link>
		<comments>http://blog.upsuper.org/ujudger-0-1-release/#comments</comments>
		<pubDate>Fri, 10 Jul 2009 02:54:48 +0000</pubDate>
		<dc:creator>upsuper</dc:creator>
				<category><![CDATA[小程序]]></category>
		<category><![CDATA[Cena]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[OI]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[ujudger]]></category>

		<guid isPermaLink="false">http://blog.upsuper.org/?p=781</guid>
		<description><![CDATA[曾经的曾经，很早很早以前，我发布了一个叫 ujudger-base 0.1 的东西，是用 C++ 写成的简单测评程序，仅能测试程序运行时间和内存耗用（还不准确）。 这次发布的是一个完整的测评机，支持传统题型、交互题和提交答案题，可导出测评结果。整个程序使用 Python 编写，直接把 ujudger.py 复制到待测目录下并编写 config 文件即可测评。 不过现在这个程序只有一个文字界面，非常简陋，而且安全性不佳。但现在正在撰写的 ujudger 1.0 (版本跨越大，意味着变化之巨大……) 将就这些问题有重大改进，敬请期待。 另外，有人询问是否准备让这个测评机与另一个 Windows 下的开源测评机 Cena 兼容。我的回答是，由于设计差异，可能比较困难。对比 Cena 的自定义校验器，ujudger 的自定义校验器更强大，同时 Cena 的校验器可以通过一点简单的修改或加一个脚本外壳就可以在 ujudger 中使用。在 1.0 中计划兼容 Cena 的校验器。至于配置文件，1.0 中配置文件的格式会有较大变动，不过可能可以通过转换程序将 Cena 的配置文件转为 ujudger 的。 我在 Google Code 上开了一个项目，感兴趣的同学可以关注关注~地址：http://ujudger.googlecode.com/ 最后，ujudger 0.1 的下载地址也在 Google Code 上：ujudger.py]]></description>
			<content:encoded><![CDATA[<p>曾经的曾经，很早很早以前，<a href="http://blog.upsuper.org/ujudger-base-0-1-released/">我发布了一个叫 ujudger-base 0.1 的东西</a>，是用 C++ 写成的简单测评程序，仅能测试程序运行时间和内存耗用（还不准确）。</p>
<p>这次发布的是一个完整的测评机，支持传统题型、交互题和提交答案题，可导出测评结果。整个程序使用 Python 编写，直接把 ujudger.py 复制到待测目录下并编写 config 文件即可测评。</p>
<p>不过现在这个程序只有一个文字界面，非常简陋，而且安全性不佳。但现在正在撰写的 ujudger 1.0 (版本跨越大，意味着变化之巨大……) 将就这些问题有重大改进，敬请期待。</p>
<p>另外，有人询问是否准备让这个测评机与另一个 Windows 下的开源测评机 Cena 兼容。我的回答是，由于设计差异，可能比较困难。对比 Cena 的自定义校验器，ujudger 的自定义校验器更强大，同时 Cena 的校验器可以通过一点简单的修改或加一个脚本外壳就可以在 ujudger 中使用。在 1.0 中计划兼容 Cena 的校验器。至于配置文件，1.0 中配置文件的格式会有较大变动，不过可能可以通过转换程序将 Cena 的配置文件转为 ujudger 的。</p>
<p>我在 Google Code 上开了一个项目，感兴趣的同学可以关注关注~地址：<a href="http://ujudger.googlecode.com/">http://ujudger.googlecode.com/</a></p>
<p>最后，ujudger 0.1 的下载地址也在 Google Code 上：<a href="http://ujudger.googlecode.com/files/ujudger.py">ujudger.py</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.upsuper.org/ujudger-0-1-release/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>ujudger-base 0.1 编写小结</title>
		<link>http://blog.upsuper.org/summary-of-ujudger-base-0-1-programming/</link>
		<comments>http://blog.upsuper.org/summary-of-ujudger-base-0-1-programming/#comments</comments>
		<pubDate>Mon, 30 Jun 2008 03:38:24 +0000</pubDate>
		<dc:creator>upsuper</dc:creator>
				<category><![CDATA[探究学习]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[ujudger]]></category>
		<category><![CDATA[源代码]]></category>

		<guid isPermaLink="false">http://blog.upsuper.org/?p=124</guid>
		<description><![CDATA[昨天说今天要写一篇来说说 ujudger-base 用到的技术层的资料，今天就来试着写一写，顺便自己复习一下相关的东西。 这些大多是参考网上资料及 man 手册得到的，有错误的地方请多指教！ 最早查早的资料是关于创建子进程的。在查找了很多资料后，我发现，在 Linux 下创建子进程只有一个方法—— fork 函数和 vfork 函数。两个函数有些许的不同，但他们的用法却大体相同，即从调用函数开始，程序分岔为父进程和子进程两个完全相同的程序。最神奇的地方出现了：这个函数一旦调用成功将会返回两次！不知道在哪里看到这个说明，让我瞬间领悟了这个函数的用法。这个函数会在父进程和子进程各返回一次，父进程中返回子进程的 pid ，子进程中返回 0。如果调用错误，则返回一次 -1，并将具体的错误编号放入 errno （需引用 errno.h）。于是我们可以用一个很简短的程序来说明这个函数的用法： 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 #include &#60;iostream&#62; extern &#34;C&#34; &#123; #include [...]]]></description>
			<content:encoded><![CDATA[<p>昨天说今天要写一篇来说说 ujudger-base 用到的技术层的资料，今天就来试着写一写，顺便自己复习一下相关的东西。</p>
<p>这些大多是参考网上资料及 man 手册得到的，有错误的地方请多指教！<br />
<span id="more-124"></span><br />
最早查早的资料是关于创建子进程的。在查找了很多资料后，我发现，在 Linux 下创建子进程只有一个方法—— fork 函数和 vfork 函数。两个函数有些许的不同，但他们的用法却大体相同，即从调用函数开始，程序分岔为父进程和子进程两个完全相同的程序。最神奇的地方出现了：这个函数一旦调用成功将会返回两次！不知道在哪里看到这个说明，让我瞬间领悟了这个函数的用法。这个函数会在父进程和子进程各返回一次，父进程中返回子进程的 pid ，子进程中返回 0。如果调用错误，则返回一次 -1，并将具体的错误编号放入 errno （需引用 errno.h）。于是我们可以用一个很简短的程序来说明这个函数的用法：</p>

<div class="wp_codebox"><table><tr id="p1248"><td class="line_numbers"><pre>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
</pre></td><td class="code" id="p124code8"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #0000ff;">extern</span> <span style="color: #FF0000;">&quot;C&quot;</span> <span style="color: #008000;">&#123;</span>
	<span style="color: #339900;">#include &lt;unistd.h&gt;</span>
	<span style="color: #339900;">#include &lt;sys/types.h&gt;</span>
	<span style="color: #339900;">#include &lt;errno.h&gt;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span> argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">int</span> child <span style="color: #000080;">=</span> fork<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>child <span style="color: #000080;">==</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;This is subprocess! &quot;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;My pid is &quot;</span> <span style="color: #000080;">&lt;&lt;</span> getpid<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
	<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>child <span style="color: #000080;">==</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;An error occurred! &quot;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;Error Number: &quot;</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #0000ff;">errno</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
	<span style="color: #0000ff;">else</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;This is parent process! &quot;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;My pid is &quot;</span> <span style="color: #000080;">&lt;&lt;</span> getpid<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;My child's pid is &quot;</span> <span style="color: #000080;">&lt;&lt;</span> child <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>创建了子进程就要运行别的程序了，在 Linux 中需要使用 exec 族函数。这些函数包括：</p>

<div class="wp_codebox"><table><tr id="p1249"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p124code9"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span> execl<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>path, <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>arg, ...<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span> execlp<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>file, <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>arg, ...<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span> execle<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>path, <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>arg,
    ..., <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span> <span style="color: #0000ff;">const</span> envp<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span> execv<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>path, <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span><span style="color: #0000ff;">const</span> argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span> execvp<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>file, <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span><span style="color: #0000ff;">const</span> argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>他们的不同用法可以参考 man 手册，不过我个人比较喜欢 execl 所以就小小介绍一下。execl 是我认为这里面最简单的一个函数了！用法就是 execl(欲执行的程序的绝对路径, 参数0, 参数1, &#8230;, NULL); 如果不返回就调用成功了（又一个奇怪的函数），因为原来的进程内容被新的程序覆盖了。返回就说明必定出错……同样的错误代码存于 errno。下面用一个小小的程序来说明一下：</p>

<div class="wp_codebox"><table><tr id="p12410"><td class="line_numbers"><pre>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
</pre></td><td class="code" id="p124code10"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #0000ff;">extern</span> <span style="color: #FF0000;">&quot;C&quot;</span> <span style="color: #008000;">&#123;</span>
	<span style="color: #339900;">#include &lt;unistd.h&gt;</span>
	<span style="color: #339900;">#include &lt;errno.h&gt;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span> argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">int</span> child <span style="color: #000080;">=</span> fork<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>child <span style="color: #000080;">==</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		execl<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;/bin/ls&quot;</span>, <span style="color: #FF0000;">&quot;ls&quot;</span>, <span style="color: #FF0000;">&quot;..&quot;</span>, <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;An error occurred in execl()! &quot;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;Error Number: &quot;</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #0000ff;">errno</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
	<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>child <span style="color: #000080;">==</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;An error occurred in fork()! &quot;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;Error Number: &quot;</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #0000ff;">errno</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
	<span style="color: #0000ff;">else</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;This is parent process!&quot;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>其中 execl 的参数 0 是必须要有的，可以为空串或者欲执行程序的名称（如该例中为 ls）。使用过 C++ 的 argv 的应该都知道，argv[0] 是程序名称。参数列表要以一个 NULL 结尾，否则应该会出错。另外就是，欲执行的程序也可以用形如“./prog”来表示运行当前目录下的程序。</p>
<p>开始的时候我有些不明白，Linux 为什么要弄得这么麻烦，多一个步骤。不过后来想想，觉得这样也不错，父进程甚至可以“要求”子进程做一些事情，比如 ptrace me…… <img src='http://blog.upsuper.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>下面来说说关于获取进程运行时间和占用内存的问题。我原来想单单通过 getrusage 函数来获取，但后来发现这个函数不但获取不了内存耗用（返回 0），而且也不能了解程序是否结束……后来发现一个很不错的函数 wait4 ，拥有全部 getrusage 的功能，并且还更强大！根据 man 手册，wait4 的定义是 pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage); 这告诉我们，wait4 不但可以返回 rusage 结构的资料，还有退出时的返回值 status （突然想起来，ujudger-base 0.1 里忘记监视 status 的值了……）。同时，man 手册告诉我们，如果 options 设为 WNOHANG ，那么函数将不会等待而立即返回，如果没有 pid 指定的进程已经结束，则返回 0。这样我们就有了一个可以等待程序结束的方法了！不过这里获得的 rusage 其实和 getrusage 一样，只有时间可以收集到……收集到的时间是以 struct timeval 的格式存储的，timeval 的定义为：</p>

<div class="wp_codebox"><table><tr id="p12411"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p124code11"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">struct</span> timeval <span style="color: #009900;">&#123;</span>
	time_t		tv_sec<span style="color: #339933;">;</span>     <span style="color: #808080; font-style: italic;">/* seconds */</span>
	suseconds_t	tv_usec<span style="color: #339933;">;</span>    <span style="color: #808080; font-style: italic;">/* microseconds */</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>一个是秒，一个是微秒（1μs=1&#215;10<sup>-6</sup>s），还是蛮精确的吧？</p>
<p>有了这个，我们还需要一点东西，来等待。虽然 wait4 可以自己等待，但我们不希望他在等待的时候我们什么也不能做不是？经过查找，我发现 Linux 下有一个叫 sleep 的函数，但这个函数的等待时间单位是秒……我觉得好郁闷……后来知道还有一个叫 usleep 的函数，等待时间是以微秒记，这才是我们需要的！（虽然根据实验，这个函数的计时是有点误差的）下面把前面的函数全部联合起来写一个小程序（我觉得已经有些许接近 ujudger-base 0.1 了……）：</p>

<div class="wp_codebox"><table><tr id="p12412"><td class="line_numbers"><pre>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
34
35
36
37
38
39
40
41
</pre></td><td class="code" id="p124code12"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #0000ff;">extern</span> <span style="color: #FF0000;">&quot;C&quot;</span> <span style="color: #008000;">&#123;</span>
	<span style="color: #339900;">#include &lt;unistd.h&gt;</span>
	<span style="color: #339900;">#include &lt;errno.h&gt;</span>
	<span style="color: #339900;">#include &lt;sys/types.h&gt;</span>
	<span style="color: #339900;">#include &lt;sys/time.h&gt;</span>
	<span style="color: #339900;">#include &lt;sys/resource.h&gt;</span>
	<span style="color: #339900;">#include &lt;sys/wait.h&gt;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span> argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">int</span> child <span style="color: #000080;">=</span> fork<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>child <span style="color: #000080;">==</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		execl<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;./test&quot;</span>, <span style="color: #FF0000;">&quot;&quot;</span>, <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;An error occurred in execl()! &quot;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;Error Number: &quot;</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #0000ff;">errno</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
	<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>child <span style="color: #000080;">==</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;An error occurred in fork()! &quot;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;Error Number: &quot;</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #0000ff;">errno</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
	<span style="color: #0000ff;">else</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;This is parent process!&quot;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;Start waiting...&quot;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
		<span style="color: #0000ff;">int</span> status<span style="color: #008080;">;</span>
		rusage usage<span style="color: #008080;">;</span>
		<span style="color: #0000ff;">while</span> <span style="color: #008000;">&#40;</span>wait4<span style="color: #008000;">&#40;</span>RUSAGE_CHILDREN, <span style="color: #000040;">&amp;</span>status, WNOHANG, <span style="color: #000040;">&amp;</span>usage<span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
		<span style="color: #008000;">&#123;</span>
			usleep<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">100</span> <span style="color: #000040;">*</span> <span style="color: #0000dd;">1000</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// Sleep for 100ms</span>
		<span style="color: #008000;">&#125;</span>
		<span style="color: #0000ff;">double</span> usertime <span style="color: #000080;">=</span> <span style="color: #0000ff;">static_cast</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>usage.<span style="color: #007788;">ru_utime</span>.<span style="color: #007788;">tv_sec</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">+</span> 
			<span style="color: #0000ff;">static_cast</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>usage.<span style="color: #007788;">ru_utime</span>.<span style="color: #007788;">tv_usec</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">/</span> <span style="color:#800080;">1e6</span><span style="color: #008080;">;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;Time used: &quot;</span> <span style="color: #000080;">&lt;&lt;</span> usertime <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;s&quot;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>其中的“./test”的代码：</p>

<div class="wp_codebox"><table><tr id="p12413"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p124code13"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span> argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;Test start!&quot;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
	<span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000dd;">1000000000</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;Test end!&quot;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>测 ujudger-base 的时候也是用类似的程序测试的。</p>
<p>最后就是关于运行时获取程序各项信息的方法。查找了许多资料后，开始使用的读取内存耗用的方法是读取 /proc/&lt;pid&gt;/statm 文件的方法，后来使用因为想要实时获取已经耗用的时间而最终转而读取 /proc/&lt;pid&gt;/stat 文件。这两个文件的相关说明在“man proc”中已经很详细了，这里就不一一说明了。我所用到的是 stat 里面的 utime 和 rss。utime 获取的单位为 jiffies，将其转换为时间需要一个宏 JIFFIES_TO_NS。我在 include 里面没有找到这个宏的定义，这里给出来：</p>

<div class="wp_codebox"><table><tr id="p12414"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p124code14"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;sys/param.h&gt; // For HZ below</span>
<span style="color: #339933;">#define JIFFIES_TO_NS(TIME) ((TIME) * (1000000000 / HZ))</span></pre></td></tr></table></div>

<p>这个宏将 jiffies 转换为纳秒（1ns=1&#215;10<sup>-9</sup>s）。而 rss 获取的内存单位为 pages，可以将其乘以 getpagesize 函数来获得进程占用的内存空间（单位：字节）。不过这里的 rss 获得的似乎和系统监视器中获得的数据不大一样，根据对比，系统监视器获得的应该是 statm 文件中的 data 数据。这个部分的代码可以参看 ujudger-base 中getrunstat 函数。</p>
<p>总体上说，这次这个 ujudger-base 0.1 中用到的技术就这些了。写的同时也发现昨晚那个程序不完善的地方，一个是读取 rss 的时候直接乘4（<< 2）而不是乘以 getpagesize() ；一个是没有检验程序返回值（通常运行时错误都已这种形式表达）；还有就是没有处理 execl 可能发生的错误……稍微修改一下……</p>
<p>发布修改后的新版本：<a href="http://ujudger.upsuper.org/src/ujudger-base-0.1.1.cpp">ujudger-base-0.1.1.cpp</a> (3.9 KB)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.upsuper.org/summary-of-ujudger-base-0-1-programming/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ujudger-base 0.1 Released</title>
		<link>http://blog.upsuper.org/ujudger-base-0-1-released/</link>
		<comments>http://blog.upsuper.org/ujudger-base-0-1-released/#comments</comments>
		<pubDate>Sun, 29 Jun 2008 14:45:21 +0000</pubDate>
		<dc:creator>upsuper</dc:creator>
				<category><![CDATA[我的计划]]></category>
		<category><![CDATA[C/C++/C#]]></category>
		<category><![CDATA[GPL]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[ujudger]]></category>
		<category><![CDATA[源代码]]></category>

		<guid isPermaLink="false">http://blog.upsuper.org/?p=122</guid>
		<description><![CDATA[经过我许多的资料查找和编写，终于完成了ujudger-base的第一个版本！ ujudger 是我准备编写的基于 Linux 的测评程序，采用 GPL 协议。由于一直以来找不到 Linux 下的测评程序，因此准备自己写一个。ujudger 的 u 既是取我网名的第一个字母，也是 ubuntu 的第一个字母，表示这个程序应该会在 ubuntu 下完成编写。而 ujudger-base 是 ujudger 的基础程序，表现 ujudger 的测评核心，即耗时和内存耗用的取得。使用 time 命令和系统监视器监视器的资料对比一下，ujudger-base 获得的信息还是比较体现程序的真实情况的。 ujudger-base 并不复杂，不过也不简单（自少我这么觉得）。在编写的过程中，开始不知道 Linux 下的进程控制，后来知道了 fork() 函数。开始觉得很奇怪，后来也就慢慢明白了。不就是返回两次么，有什么了不起的~然后就是exec族的函数，成功了就不返回了_-b 然后就是等待的办法。网上有些人是直接用 wait4 快速返回来等待，但我觉得这样很影响速度，因此采用了 usleep 等待 100ms（有没有一点像 Cena 的方法？）。 同时，我还查找了有关程序运行数据读取的相关问题，最后采用的是读取 /proc/&#60;pid&#62;/stat 文件的方法。具体采用的一些技术层的资料我准备明天发一篇来讲。 除此之外就是几乎第一次大规模的采用 C++ 的推荐风格编写程序（以前写OI的程序，为了效率不得不放弃许多 C++ 优美的特性），因此有写丑的地方也请多多指教。 里面的注释很多了，由于我的英语水平有限（My English is limited!），如果注释有什么语法错误，也请多多指教！ 点击这里下载源代码：ujudger-base-0.1.cpp (3.6 KB)]]></description>
			<content:encoded><![CDATA[<p>经过我许多的资料查找和编写，终于完成了ujudger-base的第一个版本！</p>
<p>ujudger 是我准备编写的基于 Linux 的测评程序，采用 GPL 协议。由于一直以来找不到 Linux 下的测评程序，因此准备自己写一个。ujudger 的 u 既是取我网名的第一个字母，也是 ubuntu 的第一个字母，表示这个程序应该会在 ubuntu 下完成编写。而 ujudger-base 是 ujudger 的基础程序，表现 ujudger 的测评核心，即耗时和内存耗用的取得。使用 time 命令和系统监视器监视器的资料对比一下，ujudger-base 获得的信息还是比较体现程序的真实情况的。<br />
<span id="more-122"></span><br />
ujudger-base 并不复杂，不过也不简单（自少我这么觉得）。在编写的过程中，开始不知道 Linux 下的进程控制，后来知道了 fork() 函数。开始觉得很奇怪，后来也就慢慢明白了。不就是返回两次么，有什么了不起的~然后就是exec族的函数，成功了就不返回了_-b</p>
<p>然后就是等待的办法。网上有些人是直接用 wait4 快速返回来等待，但我觉得这样很影响速度，因此采用了 usleep 等待 100ms（有没有一点像 Cena 的方法？）。</p>
<p>同时，我还查找了有关程序运行数据读取的相关问题，最后采用的是读取 /proc/&lt;pid&gt;/stat 文件的方法。具体采用的一些技术层的资料我准备明天发一篇来讲。</p>
<p>除此之外就是几乎第一次大规模的采用 C++ 的推荐风格编写程序（以前写OI的程序，为了效率不得不放弃许多 C++ 优美的特性），因此有写丑的地方也请多多指教。</p>
<p>里面的注释很多了，由于我的英语水平有限（My English is limited!），如果注释有什么语法错误，也请多多指教！</p>
<p>点击这里下载源代码：<a href="http://ujudger.upsuper.org/src/ujudger-base-0.1.cpp">ujudger-base-0.1.cpp</a> (3.6 KB)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.upsuper.org/ujudger-base-0-1-released/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

