<p>由于特权在类Unix系统和Windows上的工作方式完全不同,因此需要有特定于平台的代码。在任何情况下,您都需要将程序分为两个单独的程序,一个使用提升的权限运行,另一个使用标准/降低的权限运行。</p>
<p>在类Unix系统(包括Linux和Mac OS X)中,使用提升权限运行的可执行文件应执行以下操作:</p>
<ol>
<li>假设您以根用户身份运行并打开文件进行读取。既然你提到这个文件很大,你实际上并没有把整个文件都读入,你只需要保持一个打开的文件描述符。如果打开失败,则打印错误消息并退出。</li>
<li>使用<a href="http://linux.die.net/man/2/setreuid" rel="nofollow">^{<cd1>}</a>和<a href="http://linux.die.net/man/2/setreuid" rel="nofollow">^{<cd2>}</a>将您的用户ID和组ID设置回非特权用户。</li>
<li>使用<a href="http://linux.die.net/man/3/exec" rel="nofollow">^{<cd3>}</a>函数之一执行未授权的可执行文件。</li>
<li>如果您想使其不使用<code>sudo</code>即可运行此程序,则将其归root所有,并使用<code>chown root the-program; chmod +s the-program</code>将其设置为可执行的用户ID。</li>
</ol>
<p>未授权的程序现在将以正常权限运行,但当它启动时,它将有一个打开的文件描述符(文件描述符3),可用于从特殊文件中读取。</p>
<p>对于Windows,它类似但略有不同:</p>
<ol>
<li>假设您以根用户身份运行,并使用<a href="http://msdn.microsoft.com/en-us/library/aa363858%28v=vs.85%29.aspx" rel="nofollow">^{<cd6>}</a>打开要读取的文件。不要使用默认的安全属性——创建一个<code>SECURITY_ATTRIBUTES</code>结构,将<code>bInheritHandle</code>设置为<code>TRUE</code>,以便子进程继承句柄。如果打开文件失败,请打印错误消息并退出。</li>
<li>使用<a href="http://msdn.microsoft.com/en-us/library/ms682425%28v=vs.85%29.aspx" rel="nofollow">^{<cd10>}</a>启动子进程。在命令行上传入上面的句柄(例如,打印为数值);您也可以<a href="http://blogs.msdn.com/b/oldnewthing/archive/2003/12/11/56043.aspx" rel="nofollow">use a shared memory region</a>,但这比这个问题值得的麻烦多。</li>
<li><a href="http://msdn.microsoft.com/en-us/library/bb756929.aspx" rel="nofollow">Embed a manifest</a>在此可执行文件中,<code>requireAdministrator</code>设置为<code>true</code>。执行此操作后,当您运行程序时,将收到一个UAC提示,询问您是否希望允许程序进行更改。</li>
</ol>
<p>然后,子进程通过解析命令行来获取继承的句柄,然后它可以随心所欲地读入数据。</p>
<P>这种方法的一个问题是,当继承句柄时,必须使用低级系统调用(在{Unix上的CD13>},^ {CD14>}在Windows上)从中读取——不能使用诸如C ^ ^ {CD15>}或C++ ^ {CD16>}s的高级函数(OK,UNIX具有^ {CD17>},但在我所知的Windows上没有等价物)。</p>
<p>我相信您现在已经注意到了,上面的所有内容都是用C语言编写的。在Unix中,这相当直接地转化为Python,因为<a href="http://docs.python.org/library/os.html" rel="nofollow">^{<cd18>} module</a>有很多优点,比如<code>setreuid</code>、<code>exec*</code>和<code>fdopen</code>。在Windows上,您可以使用<code>ctypes</code>模块和/或<a href="http://sourceforge.net/projects/pywin32/" rel="nofollow">Pywin32</a>来完成这些工作,但是使用C可能更容易</p>