湖南科技大学操作系统课程设计实验报告

更新时间:2023-05-04 21:13:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

操作系统课程设计实验报告

课程名称:操作系统

班级:10级计算机二班

姓名:朱志刚

学号:1005010214

指导教师:黄卫红

评分:

实验日期:2012 年 6 月17日

1

1、实验名称:任务一I/O系统的调用开销比较

2、实验目的:

了解I/O系统调用的特点并通过性能测试对此有直观的认识

3、实验思路

1、先根据题目生成所需的4kb,256kb,64mb的txt文件

2、根据main函数的int main (int argc, char *argv[])参数特性,可以设计成:

if (4 != argc)

{

printf ("输入格式错误!\n") ;

exit(0) ;

}

来确定输入参数是4个

/*----------------------------------------------------------------

@argc[0] ./你的程序名

@argc[1] 用于测试的文件名

@argv[2] 选择的操作方式fopen、open或者mmap的方式

"1":标准C的I/O库函数fopen fread fwrite

"2":Unix的I/O函数open read write

"3":open和mmap

@argv[3] read/fread读取的字节数大小

-----------------------------------------------------------------*/

最后根据相应的功能实现相应的操作

4、具体实验内容

6月4日

参阅了百度上的说法,了解到mmap函数参数是一种映射方式的执行的,它可以最快速的运行程序,而且只是开始的时候系统调用,大大减少了系统的开销,我思考了下这道题的具体解决方式,决定用switch语句提供选择性的操作,用一个cpp文件把所有的功能都包含进去,再次之前我我写了个交换函数

void reverse (char *str)

{

int i, strLen = strlen (str), half = strLen / 2 ;

char c ;

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

{

2

c = str[i] ;

str[i] = str[strLen - i - 1] ;

str[strLen - i - 1] = c ;

}

}

随便写了读取文件的基本测试。

6月5日和6月6日

我先写了个制作函数,分别用于生成所需大小的文件然后写完了剩下的函数

关键代码:

if (1 == type)//打开文件

file = fopen (argv[1], "r+") ;

else

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

if (1 == type)

{

fseek(file, 0L, SEEK_END) ;

fileLen = ftell (file) ;

fseek(file, 0L, SEEK_SET) ;

}

else

{

fstat (handle, &statbuf) ;

fileLen = statbuf.st_size ;

}

while (curLen < fileLen - 1)//获取文件大小

{

if (1 == type)

fread (str, 1, block, file) ;

else if (2 == type)

read (handle, str, block) ;

else

str = mmap (0, block, PROT_READ, MAP_PRIV A TE | MAP_NORESERVE, handle, curLen) ;

strcat (text, str) ;

curLen += block ;

}

reverse (text) ;//逆序

if (1 == type)//重归位

fseek(file, 0L, SEEK_SET) ;

else

lseek (handle, 0L, SEEK_SET) ;

3

for (curLen = 0; curLen < fileLen; curLen += block)//对应读取

{

if (1 == type)

fwrite (text, 1, block, file) ;

else if (2 == type)

write (handle, text, block) ;

else

{

str = mmap (0, block, PROT_WRITE, MAP_PRIV A TE | MAP_NORESERVE, handle, curLen) ;

strcpy (str, text) ;

}

text += block ;

}

text -= fileLen;

free (text) ;

free (str) ;

if (1 == type)

fclose (file) ;

else

close (handle) ;

return 0 ;

}

5、测试:

4

6、实验心得体会

通过做任务一,系统的调用的开销大小,我明白了应尽量减少系统的调用从而提高程序运行的速度,多用数据结构和算法提高整体的运行速度,减少时间复杂度和空间复杂度,对于读取的时候和逆序的时候要考虑到效率问题,测试的时候,经过老师的讲解,学到了很多,应尽量考虑到硬件的支持,相信在以后会学得的更多。

1、实验名称:任务二实现一个简单的shell

2、实验目的:

实现一个简单的shell(命令行解释器),类似于bash, csh等。本设计的主要目的在于学会如何在Unix系统下创建进程和管理进程。

5

3、实验思路

先判断输入的是什么命令,在判断命令是否为内部命令,是内部命令则根据自定义函数分别实现相应的功能,非内部命令则调用进程和应用系统自带的内部命令,打开文档分别执行内部的命令,总体思路非常清晰只要熟练相应的函数调用,和各自的实现的功能。

4、具体实验内容

6月7日

参阅了一些资料

了解到ssize_t这个数据类型用来表示可以被执行读写操作的数据块的大小。它和size_t类似, 但必需是signed.意即:它表示的是signed size_t类型的(typedef signed int ssize_t)。

char *getcwd(char *buf, size_t size); 把当前目录的绝对地址保存到 buf 中,buf 的大小为 size。如果 size太小无法保存该地址,返回 NULL 并设置 errno 为 ERANGE。可以采取零 buf 为 NULL并使 size 为负值来使 getcwd 调用 malloc 动态给 buf 分配,但是这种情况要特别注意使用后释放缓冲以防止内存泄漏。

int execvp(const char *file, char *const argv[]);execvp()会从PATH 环境变量所指的目录中查找符合参数file 的文件名,找到后便执行该文件,然后将第二个参数argv 传给该欲执行的文件。

6月8日

我先实现一些简单的命令内部命令

/*

* if args == quit

*/

int isquit(char *arg)

{

//int strcmp(const char *s1, const char *s2);

if(strcmp(arg, "quit") == 0 || strcmp(arg, "exit") == 0 || strcmp(arg, "bye") == 0 )

{

return 1;

}

else

{

return 0;

}

}

6

/*

* likes shell's cd

*/

int shell_cd(char *args[])

{

char buf[BUFSIZE + 1];

memset(buf, 0, BUFSIZE + 1);

if(args[1][0] != '/' && args[1][0] != '.'){

//char *getcwd(char *buf, size_t size);

if(getcwd(buf, BUFSIZE) == NULL){

fprintf(stderr, "%s:%d: getcwd failed: %s\n", __FILE__,

__LINE__, strerror(errno));

return -1;

}

strncat(buf, "/", BUFSIZE - strlen(buf));

}

//char *strncat(char *dest, const char *src, size_t n);

strncat(buf, args[1], BUFSIZE - strlen(buf));

#if DEBUG

fprintf(stdout, "%s\n", buf);

#endif

//int chdir(const char *path);

if(chdir(buf) == -1){

fprintf(stderr, "%s:%d: chdir failed: %s\n", __FILE__,

__LINE__, strerror(errno));

}

return 0;

}

/*

* fork and called exec

*/

int shell_help (char *args[])

{//int strcmp(const char *s1, const char *s2);

if(strcmp(args[0],"help") == 0 )

{

printf("The SimpleShell of Evel\n\n");

printf("The list of commands.\n\n");

7

printf(" dir\t\tList the files and dirs.\n");

printf(" cd\t\tChange the dir.\n");

printf(" clear\t\tClear the screen.\n");

printf(" environ\tList all the environment variable string settings.\n");

printf(" echo\t\tDisplay echo content and wrap.\n");

printf(" help\t\tA brief introduction to the shell use.\n");

printf(" quit,exit,bye\t\tExit shell.\n");

printf("For more information add type help before command.\n\n");

printf("Notice:All the command line is lowercase letter distinction!\n\n");

}

return 0;

}

int shell_echo(int num,char *args[])

{

int i;

char buf[BUFSIZE + 1];

//void *memset(void *s, int c, size_t n);

memset(buf, 0, BUFSIZE + 1);

//memset(buf, 0, sizeof(buf));

for( i = 1; i < num; i++)

sprintf(buf, "%s%s ",buf, args[i]);

fprintf(stdout, "%s\n", buf);

// printf("%s",buf);

return 0;

}

int shell_environ (char *args[])

{

char *p;

if( (p=getenv("PATH")) )

{

printf(" PATH = %s\n",p);

}

if( (p=getenv("HOME")) )

{

printf(" HOME = %s\n",p);

}

if( (p=getenv("HISTSIZE")) )

{

printf(" HISTSIZE = %s\n",p);

}

8

if( (p=getenv("LOGNAME")) )

{

printf(" LOGNAME = %s\n",p);

}

if( (p=getenv("HOSTNAME")) )

{

printf(" HOSTNAME = %s\n",p);

}

if( (p=getenv("SHELL")) )

{

printf(" SHELL = %s\n",p);

}

if( (p=getenv("LANGUGE")) )

{

printf(" LANGUGE = %s\n",p);

}

if( (p=getenv("MAIL")) )

{

printf(" MAIL = %s\n",p);

}

if( (p=getenv("PS1")) )

{

printf(" PS1 = %s\n\n",p);

}

return 0;

}

6月11日

实现了部分内部命令

/*

* fork and called exec

*/

int shell_fork(char *args[])

{

pid_t pid[CMDNUMBER];

int status;

int fork_num;

char **p; /* point args */

char *q; /* point *args */

/* get numbers of child process*/

fork_num = 1;

p = args;

9

while(*p != NULL){

q = *p;

while(*q != '\0'){

if(*q == '|'){

fork_num++;

}

q++;

}

p++;

}

#if DEBUG

fprintf(stdout, "fork_num = %d\n", fork_num);

#endif

/* case: child process number is one */

if(fork_num < 2){

//pid_t fork(void);

if((pid[0] = fork()) < 0){

/* error */

perror("fork");

exit(1);

}else if(pid[0] == 0){

/* child process */

//int execvp(const char *file, char *const argv[]);

if(execvp(args[0], args) < 0){//execvp()会从PATH 环境变量所指的目录中查找符合参数file 的文件名,找到后便执行该文件,然后将第二个参数argv传给该欲执行的文件。

perror("");

exit(1);

}

exit(0);

}

}

/* parent process */

//pid_t waitpid(pid_t pid, int *status, int options);

if(fork_num < 2){

waitpid(pid[0], &status, 0);

}else{

//int mutifork(char *args[])

status = mutifork(args);

}

return status;

}

int mutifork(char *args[])

10

{

int pipefd[CMDNUMBER][2];

pid_t pid[CMDNUMBER];

int i, j;

int count;

int status;

char **arg_child[CMDNUMBER];

char **p;

char ***q;

/* parse and split args to child arg */

count = 0;

p = args; q = arg_child;

while(*p != NULL && p != NULL){

*q++ = p;

count++;

while(*p != NULL && strcmp(*p, "|") != 0){

p++;

}

if(*p != NULL){

*p++ = NULL;

}

}

*q = NULL;

#if DEBUG /* check child args */

fprintf(stdout, "----------------------------------------\n");

fprintf(stdout, "count = %d\n", count);

q = arg_child; i = 0;

while(*q != NULL){

p = *q++;

while(*p != NULL){

fprintf(stdout, "[%d]%s\n", i, *p++);

}

i++;

}

#endif

/* fork count child process */

for(i = 0; i < count; i++){

/* init pipe file descriptor */

if(pipe(pipefd[i]) < 0){ /* FIXME: excess one */

perror("pipe");

return -1;

}

/* fork child i */

if((pid[i] = fork()) < 0){

11

fprintf(stderr, "%s:%d: fork() failed: %s\n", __FILE__,

__LINE__, strerror(errno));

return -1;

}else if(pid[i] == 0){

/* child i */

//int dup2(int oldfd, int newfd);

if(i == 0){ /* the first child */

close(pipefd[i][0]); /* close curr process read */

if(dup2(pipefd[i][1], STDOUT_FILENO) < 0){

perror("dup2 failed");

return -1;

}

}else if(i == count - 1){ /* the last child */

for(j = 0; j < i - 1; j++){ /* close unuse pipefd */

close(pipefd[j][1]);

close(pipefd[j][0]);

}

close(pipefd[j][1]); /* close prev process end of write */

close(pipefd[i][0]); /* close curr process end of read */

if(dup2(pipefd[j][0], STDIN_FILENO) < 0){

perror("dup2 failed");

return -1;

}

}else{

for(j = 0; j < i - 1; j++){ /* close unuse pipefd */

close(pipefd[j][1]);

close(pipefd[j][0]);

}

close(pipefd[j][1]); /* close prev process end of write */

close(pipefd[i][0]); /* close curr process end of read */

if(dup2(pipefd[j][0], STDIN_FILENO) < 0){

perror("dup2 failed");

return -1;

}

if(dup2(pipefd[i][1], STDOUT_FILENO) < 0){

perror("dup2 failed");

return -1;

}

}

//int execvp(const char *file, char *const argv[]);

if(execvp(arg_child[i][0], arg_child[i]) < 0){

fprintf(stderr, "%s:%d: fork() failed: %s\n", __FILE__,

12

__LINE__, strerror(errno));

exit(1);

}

exit(0);

/* child process exit */

}

}

/* parent process */

for(i = 0; i < count; i++){

/* close all pipe file descriptor */

close(pipefd[i][0]);

close(pipefd[i][1]);

for(i = 0; i < count; i++){

//pid_t waitpid(pid_t pid, int *status, int options);

waitpid(pid[i], &status, 0);

if(status != 0){

return status;

}

}

return status;

}

5、测试:

13

6、实验心得体会

通过做任务二,了解了linux下命令的处理,通过一系列的系统调用,根据相应的命令处理一些指令,它的强大之处可以说是实现了交互性原理,充分实现机器与人的一种交流与沟通,也就是所谓的处理底层提供的简单的方式,这种方式一定程度上实现了一种互动,也就是这个程序所要表达的,提高对系统调用和对进程与线程的处理能力,学会了很多,也理解了系统对于shell的处理机制,受益匪浅。

1、实验名称:任务四文件内容的并行搜索

2、实验目的:

本任务旨在强化线程编程能力,对并行所带来的性能优势有直观的认识。

在阅读大型项目代码时,经常要搜索某个标识符,找出该标识符的声明、定义或引用的地方(某文件的哪一行)。本任务要求实现一个程序idfind,其使用格式如下:idfind [-j n] id dirname

选项 -j 指定并行线程数目。如果省略该选项,则只启动一个线程。

id表示要查找的标识符,dirname表示项目所在目录。

3、实验思路

先根据命令的指定的线程数目,用于处理文件的哪一部分,具体的实现部分,主要靠linux API对于文件的处理,下面请参照主要实验内容。

14

4、具体实验内容

6月12日

//要想熟悉这个程序的运行先参考下列几个知识点

dirent结构体成员如下,

struct dirent

{

long d_ino; // inode number 索引节点号

off_t d_off; // offset to this dirent 在目录文件中的偏移

unsigned short d_reclen; // length of this d_name 文件名长

unsigned char d_type; // the type of d_name 文件类型

char d_name [NAME_MAX+1]; // file name (null-terminated) 文件名,最长255字符

}

readdir相当于文件操作函数read,DIR结构体相当于文件操作里面的FILE结构体。

DIR结构体成员如下:

struct __dirstream

{

void *__fd; // 'struct hurd_fd' pointer for descriptor.

char *__data; // Directory block.

int __entry_data; // Entry number `__data' corresponds to.

char *__ptr; // Current pointer into the block.

int __entry_ptr; // Entry number `__ptr' corresponds to.

size_t __allocation; // Space allocated for the block.

size_t __size; // Total valid data in the block.

__libc_lock_define (, __lock) // Mutex lock for this structure.

};

typedef struct __dirstream DIR;

DIR结构体类似于FILE,是一个内部结构,以下几个函数用这个内部结构保存当前正在被读取的目录的有关信息

函数 DIR *opendir(const char *pathname),即打开文件目录,返回的就是指向DIR结构体的指针,而该指针由以下几个函数使用:

struct dirent *readdir(DIR *dp); //本函数用来读取目录。返回是dirent结构体指针

void rewinddir(DIR *dp);

int closedir(DIR *dp);

long telldir(DIR *dp);

void seekdir(DIR *dp,long loc);

关于DIR结构,我们知道这么多就可以了,没必要去再去研究他的结构成员。

关于stat结构体:

struct stat{

mode_t st_mode; //文件类型和权限信息

ino_t st_ino; //i结点标识

15

dev_t st_dev; //device number (file system)

dev_t st_rdev; //device number for special files

nlink_t st_nlink; //符号链接数

uid_t st_uid; //用户ID

gid_t st_gid; //组ID

off_t st_size; //size in bytes,for regular files

time_t st_st_atime; //最后一次访问的时间

time_t st_mtime; //文件内容最后一次被更改的时间

time_t st_ctime; //文件结构最后一次被更改的时间

blksize_t st_blksize; //best I/O block size

blkcnt_t st_blocks; //number of disk blocks allocated

};

下面来看看dup的声明:

#include

int dup(int fd);

int dup2(int fd1,int fd2);

两个均为复制一个现存的文件的描述

两个函数的返回:若成功为新的文件描述,若出错为-1;

由dup返回的新文件描述符一定是当前可用文件描述中的最小数值。用dup2则可以用fd2参数指定新的描述符数值。如果fd2已经打开,

则先关闭。若fd1=fd2,则dup2返回fd2,而不关闭它。通常使用这两个系统调用来重定向一个打开的文件描述符。

下面来看看pthread_create的声明:

#include

int pthread_create(pthread_t *thread, pthread_addr_t *arr,

void* (*start_routine)(void *), void *arg);

* thread :用于返回创建的线程的ID

* arr : 用于指定的被创建的线程的属性,函数中使用NULL,表示使用默认的属性

* start_routine : 这是一个函数指针,指向线程被创建后要调用的函数

* arg : 用于给线程传递参数

下面来看看pthread_join的声明:

函数pthread_join用来等待一个线程的结束。

头文件:#include

函数原型为:

int pthread_join(pthread_t thread, void **retval);

第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。

这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。

如果执行成功,将返回0,如果失败则返回一个错误号。

在Linux中,默认情况下是在一个线程被创建后,必须使用此函数对创建的线程进行资源回收,但是可以设置Threads attributes来设置当一个线程结束时,直接回收此线程所占用的系统资源,详细资料查看Threads attributes。

其实在Linux中,新建的线程并不是在原先的进程中,而是系统通过一个系统调用 clone()。该系统

16

copy了一个和原先进程完全一样的进程,

并在这个进程中执行线程函数。不过这个copy过程和fork不一样。 copy后的进程和原先的进程共享了所有的变量,运行环境。

这样,原先进程中的变量变动在copy后的进程中便能体现出来。

下面来看看pthread_mutex_lock

头文件:

#include

函数原型:

int pthread_mutex_lock(pthread_mutex_t *mutex);

返回值:

在成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,该函数将失败并返回对应的值。

描述:

当 pthread_mutex_lock() 返回时,该互斥锁已被锁定。调用该线程使该互斥锁的锁住。如果该互斥锁已被另一个线程锁定和拥有,则调用该线程将阻塞,直到该互斥锁变为可用为止。

对于 Solaris 线程,请参见mutex_lock 语法。

如果互斥锁类型为 PTHREAD_MUTEX_NORMAL,则不提供死锁检测。尝试重新锁定互斥锁会导致死锁。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或未锁定,则将产生不确定的行为。

如果互斥锁类型为 PTHREAD_MUTEX_ERRORCHECK,则会提供错误检查。如果某个线程尝试重新锁定的互斥锁已经由该线程锁定,则将返回错误。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或者未锁定,则将返回错误。

如果互斥锁类型为 PTHREAD_MUTEX_RECURSIVE,则该互斥锁会保留锁定计数这一概念。线程首次成功获取互斥锁时,锁定计数会设置为 1。线程每重新锁定该互斥锁一次,锁定计数就增加 1。线程每解除锁定该互斥锁一次,锁定计数就减小 1。锁定计数达到 0 时,该互斥锁即可供其他线程获取。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或者未锁定,则将返回错误。

如果互斥锁类型是 PTHREAD_MUTEX_DEFAULT,则尝试以递归方式锁定该互斥锁将产生不确定的行为。对于不是由调用线程锁定的互斥锁,如果尝试解除对它的锁定,则会产生不确定的行为。如果尝试解除锁定尚未锁定的互斥锁,则会产生不确定的行为

//编译时用gcc -Wall -o idfind idfind.c -lpthread 或者 gcc idfind.c -0 idfind -lpthread

//执行时 ./idfind -j 10 int /home/user/1005010214/123

6月13日和6月14日

#include

#include

#include

#include

#include

#include

#include

#include

#include

pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;

pthread_mutex_t mymutex0 = PTHREAD_MUTEX_INITIALIZER;

17

struct All_Dir

{

char DirName[300];

struct All_Dir *next;

};

struct All_File

{

char FileName[300];

struct All_File *next;

};

struct All_Char

{

int line;

int row;

struct All_Char *next;

};

struct All_File *F_head;

char *Objective, *Out_File, *Out_File_Error;

void *thread_function(void *arg)

{

int i, j, m;

char buff[50];

FILE *fp;

char Filename[300];

FILE *fp1;

struct All_Char *C_head, *C_p, *C_q;

while(F_head != NULL)

{

i = 1;

j = 0;

m = 0;

C_head = C_p = C_q = NULL;

pthread_mutex_lock(&mymutex);

if(F_head == NULL)

return NULL;

strcpy(Filename, F_head->FileName);

F_head = F_head->next;

pthread_mutex_unlock(&mymutex);

if(( fp = fopen(Filename, "r") ) == NULL)

fprintf(stderr, "<%s>: Cannot open!\n", Filename);

else

{

while(!feof(fp))

{

18

fread(&buff[0], 1, 1, fp);

j++;

if( buff[0] == '\n')

{

i ++;

j = 0;

}

else if( buff[0] == '\t')

j =j + 7;

if( (0 <= (int)(buff[0]) && (int)(buff[0]) < 8) || (11 == (int)(buff[0])) || ((int)(buff[0]) <= 31 && (int)(buff[0]) > 13) )

{

pthread_mutex_lock(&mymutex0);

if( (fp1 = freopen(Out_File_Error, "ab", stdout)) == NULL)

printf("Redirection failed!:\n"); //打开重定向文件

printf("<%s>: this is not a text file or Which contain nonprintable characters!: Error code:%d \n", Filename, buff[0]);

printf("<%5d line %5d row>\n\n", i, j);

fclose(fp1);

pthread_mutex_unlock(&mymutex0);

m = 2;

fclose(fp);

break;

}

}

if( m != 2)

{

j = 0;

i = 1;

m = 0;

fseek(fp, 0L, 0);

while(!feof(fp))

{

fread(&buff[m],1, 1, fp);

j ++;

if( buff[m] == '\n')

{

i ++;

j = 0;

}

else if( buff[m] == '\t')

j =j + 7;

if( buff[m] == Objective[m] )

19

{

m++;

}

else if( buff[m] == Objective[0])

{

m = 1;

}

else

m = 0;

if( Objective[m] == '\0' )

{

if(C_head == NULL)

{

C_head = (struct All_Char*)malloc( sizeof(struct All_Char) );

C_head->line = i;

C_head->row = j - m + 1;

C_head->next = NULL;

C_p = C_q = C_head;

}

else

{

C_p = (struct All_Char*)malloc( sizeof(struct All_Char) );

C_p->line = i;

C_p->row = j - m + 1;

C_p->next = NULL;

C_q->next = C_p;

C_q = C_p;

}

m = 0;

}

}

fclose(fp);

pthread_mutex_lock(&mymutex0);

if( (fp1 = freopen(Out_File, "ab", stdout)) == NULL)

printf("Redirection failed!\n"); //打开重定向文件

if(C_head != NULL)

printf("<%s>:\n", Filename);

while(C_head != NULL)

{

printf("<%5d line %5d row>\n", C_head->line, C_head->row);

C_head = C_head->next;

}

fclose(stdout);

pthread_mutex_unlock(&mymutex0);

20

}

}

}

return NULL;

}

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

{

int i, j, n;

int res;

DIR *p_dir;

FILE *FP;

char Cur_Dir[300], *Dirname;

char Search_Out[300], Search_Out_Error[300], Error_Suffix[7] = ".error\0", Out_Prefix[8] = "Search_\0";

int stdout_Desc = fileno(stdout); //获得stdout描述符

int stdout_Temp = dup(stdout_Desc); //备份stdout

struct stat buf;

struct dirent *p_dirent;

struct All_File *F_p, *F_q;

struct All_Dir *D_head, *D_p, *D_q;

if( ((argc != 3) && (argc != 5)) || ((argc == 2) && (strcmp(argv[1] , "/?")) == 0) || (argc == 5 && strcmp( argv[1], "-j" ) != 0) )

{

printf("文件内容并行搜索程序!\n");

fprintf(stderr, "Usage:%s \n", argv[0]);

fprintf(stderr, "Usage:%s [-j] [thread_numbre] \n", argv[0]);

exit(EXIT_FAILURE);

}

if( argc == 3 )

{

n = 1;

Objective = argv[1];

Dirname = argv[2];

Out_File = argv[1];

}

else

{

n = atoi(argv[2]);

Objective = argv[3];

Dirname = argv[4];

Out_File = argv[3];

}

21

本文来源:https://www.bwwdw.com/article/ng4e.html

Top