您的位置:首页 > 产品设计 > UI/UE

APUE 第三章习题 3.2 浅析

2013-03-23 09:29 267 查看
题目描述:编写一个与3.12节中dup2功能相同的函数,要求不能调用fcntl函数,并且有正确的出错处理。

题目分析:既然不能使用fcntl函数,那么我们就需要使用其他函数来达到类似的目的,这里列举出所有我们需要使用的函数。

1、 open函数:这里我们不应该指定一个文件描述符并尝试复制它,因为实际中我们不能知道我们指定的文件描述符就一定是合法的,这个文件描述符可能未被使用,如果这样的话就会导致后面一系列的操作失败。或者是这个文件描述符指向了一个已经打开,而且对用户非常重要的文件(操作不当的后果可想而知)。所以用open函数打开一个已经存在的文件是非常靠谱的,我们就可以复制open函数返回的文件描述符。当然,我们还要注意open函数调用时可能产生的错误进行处理。

2、 dup函数:在不能使用fcntl函数的情况下,dup函数是唯一的选择。注意dup函数的返回值,如果操作成功时返回可用的最小的文件描述符,出错时返回-1。当然,dup函数出错也是有可能的,比如说系统资源问题,或者是文件描述符用光(就现在的UNIX Like来说貌似不大可能,但是还是建议考虑一下)。

3、 输出函数:你需要将一些错误的信息输出到屏幕,告诉用户相关的错信息。

4、 close函数:用来关闭一个文件描述符,如果我们指定了将文件描述符a复制为b,如果文件描述符b被占用了,那么我们应该立即关闭它。

5、 atoi函数:将字符串转成数字,这个函数有可能会用到,具体需要看程序是如何实现的。

思路与实现细节:

首先我们应该用open函数打开一个文件,并获取open函数返回的文件描述符,我们假定open函数获取的文件描述符为”file_flag”,要复制成的指定文件描述符为”obj_flag”。我们要考虑下面的一些问题,比如说打开文件操作失败,文件访问权限问题或者文件不存在都会导致该问题。当然,这似乎不应该是这个程序需要重点处理的问题,我们只需要返回一个适当的错误信息就可以了,不必去进行创建文件的操作。想一想,一个程序在悄无声息的就创建了一个用户以为存在(实际原来不存在)的文件而且还对其进行了操作。当然用户可能认为这些过程都是正确的(比如那个文件原来就存在),后果有可能是难以预测的。另外,通过open函数获取的文件描述符(file_flag)很可能与你指定要复制成的文件描述符(obj_flag)相同!这就涉及到了下一个问题,我们指定的文件描述符是否合法。

指定的文件描述符不应该占用0~2这三个文件描述符,而且不能超过一个系统允许的上限,即OPEN_MAX,不过有些UNIX Like对其没有限制,但是建议指定的文件描述符(obj_flag)不要过大。如果指定的文件描述符与open函数获取的文件描述符相同当然也是不行的。如果出现文件描述符上述三种问题,应该返回错误,或者干脆让用户重新指定文件描述符。

实现dup2函数的方式并不难,我们先要保证文件描述符3到obj_flag都被占满,这个只需要不断地调用函数:”dup(file_flag)”,直到其返回的文件描述符值不小于obj_flag。同时需要将这些通过dup函数得到的文件描述符记录下来,以便于以后的释放。之后我们调用函数”close(obj_flag)”,这样就保证了小于obj_flag的所有文件描述符都被占用,而文件描述符obj_flag是可用的。接下来调用”dup(file_flag)”就可以保证了返回的文件描述值为obj_flag(为严谨起见我们还是应该对此时dup函数的返回值进行判断)。如此就实现了与dup2函数相似的功能,但是不要忘记释放那些额外占用的文件描述符,我们需要及时的将其释放。否则如果该程序进程为关闭,就可能在某些UNIX Like系统上造成文件描述符不够用的情况。使用dup函数时,我们也要考虑是否可能存在着dup函数返回一个错误的情况,这时返回一个错误并输出一些相关的警告应该就可以OK了。

这道题的思路大致如此。当然,即使是上面所有情况都考虑到了这个实现也没有足够好。因为这毕竟不是一个原子操作,如果有另外的一个进程对打开文件操作的话,上面思路实现的代码可靠性仍然没有保证。

代码参考:

#include <apue.h>

#include <fcntl.h>

#define MAXN 4096

#define exit_succeed 0

#define exit_failed -1

int cdup(const int file_flag, const int obj_flag)

{

int i;

int n;

int top;

int stack[MAXN];

top = 0;

if ((obj_flag>MAXN) || (obj_flag<3) || (obj_flag==file_flag))

{

printf("Obi_flag error!\n");

return exit_failed;

}

while ((n = dup(file_flag)) < obj_flag)

{

if (-1 == n)

{

printf("System can not make a flag!\n");

return exit_failed;

}

stack[top++] = n;

}

close(obj_flag);

if (-1 == dup(file_flag))

{

printf("Function dup error\n");

return exit_failed;

}

for (i=0; i<top; ++i)

{

close(stack[i]);

}

return exit_succeed;

}

int write_file(const int obj_flag)

{

char buf[] = "JiaoZhuV5\n";

if (write(obj_flag, buf, strlen(buf)) < 0)

{

printf("Write error\n");

return exit_failed;

}

return exit_succeed;

}

int main(int argc, char *argv[])

{

int obj_flag;

int file_flag;

if (3 != argc)

{

printf("Parameter error!\n");

return exit_failed;

}

file_flag = open(argv[1], O_RDWR);

if (-1 == file_flag)

{

printf("Errror! System can not open %s\n", argv[1]);

return exit_failed;

}

obj_flag = atoi(argv[2]);

if (exit_failed != cdup(file_flag, obj_flag))

{

if (exit_failed == write_file(obj_flag))

{

return exit_failed;

}

}

return exit_succeed;

}

上面代码仅供参考,若发现有任何不妥的地方,欢迎各位的批评指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: