首页 > > 详细

辅导OS –300698编程、OS讲解、讲解OS程序、OS辅导

PracticalCaseStudyB
OperatingSystemsProgramming–300698
1 Introduction
AShellorCommandLanguageInterpreter(CLI)isapieceofsoftwarethatprovidesasimple,
butpowerful,textualinterfaceforuserstoanoperatingsystem. InthisCaseStudyyouwill
investigatetheoperationofandimplementasimpleCLI.
2 SpeciuniFB01cation
ACLIacceptstextualinputfromtheuser,andexecutesthecommandsissued.Themainlogic
oftheCLIisgivenbelow:
main:
loop
get input line
if end of input exit
break line into words
found := false
if command is builtin
then
do_builtin(line)
found:=true
else
found:=find_and_execute(line)
end if
if not found report error
end loop
YouruniFB01rsttaskwillbetowriteaprogramthatrepeatedlyreadsalineofinputfromtheuser,
thefgets()function(seeSect.5forusageinformationofallsystemprovidedfunctions)
willhelpyouhere.YourprogramshouldendwheneitherendoftheinputuniFB01leisencountered,
ortheexactwordexitappearsintheinputastheonlywordonaline. Traditionallyboth
theFileSystemandCommandLanguagearecasesensitive,youshouldalsoimplementthis.
Yournexttaskwillbetobreakthelineupintowords,whichareseparatedbyoneormore
spaces.Theprovidedfunctiontokenize()doesthis,anditusesstrtok()internally.
Youmayusethisfunctionifyouwish,inwhichcaseyoushouldprovidedocumentationonits
operation,oryoumaywriteyourownparser.
Youshouldnextimplementthefind_and_execute()sectionofthelogicabove,
bycreatinganewprocessusingfork(),andthenuseoneoftheexec()familyoffunc-
tionstoruntheprogramrequestedbytheuserinthetextprovided.Iftherequestedprogram
cannotberunthenanappropriateerrormessageshouldbedisplayed,perror()willhelp
withthis(astherearemanyreasonswhythismayfail),andthechildprocessterminated.
1
TheCLIprocessmustpauseuntilthecreatedprocessisconcluded,wait()willneed
tobeusedhere.OncethenewprocesshasuniFB01nishedyoumustdecodeandprintouttheexit
statusofthatprocess.
Oncethisworksyoushouldaddabuiltinfunctioncdtochangetheworkingdirectoryof
theCLI.Thisbuiltinshouldalwaysusethenextwordsuppliedasthedirectorytochangeto,
failuretosupplyadestinationshouldbetreatedasanerror.Thechdir()functionwillbe
vitalhere.
Note ThislogichasaninuniFB01niteloopinit.Theappropriateplacetodeterminewhentoexitisin
themiddleoftheloop.Whentestingthesamplecode(ifused)youshouldusethe Ctrl + C
keycombinationtobreakoutoftheprogram. Donotuse Ctrl + Z ,itdoessomething
completelydifferent.
2
3 MarkingScheme
PleaseseetherubriconthevUWSsiteforthemarkingScheme.
3
4 SampleCode
Pleasenotethatinthesamplecode" "indicatesaspacecharacterinastring.
#include
#include
#include
#include
#include
#include
#include
#define MAX_LINE 4096
#define MAX_WORDS MAX_LINE/2
/* a line can have at most MAX_LINE/2 words, why? */
void tokenize(char *line, char **words, int *nwords);
/* break line into words separated by whitespace, placing them in the
array words, and setting the count to nwords */
int main()
{
char line[MAX_LINE], *words[MAX_WORDS], message[MAX_LINE];
int stop=0,nwords=0;
while(1)
{
printf("OSP CLI $ ");
/* read a line of text here */
tokenize(line,words,nwords);
/* More to do here */
}
return 0;
}
/* this function works, it is up to you to work out why! */
void tokenize(char *line, char **words, int *nwords)
{
*nwords=1;
for(words[0]=strtok(line," \t\n");
(*nwords
int fgetc(FILE *stream);
char *fgets(char *s,int size,FILE *stream);
int getc(FILE *stream);
int getchar(void);
char *gets(char *s);
int ungetc(int c,FILE *stream);
DESCRIPTION
fgetc() reads the next character from stream and returns it as an unsigned char cast to an int,or EOF on
end of file or error.
getc() is equivalent to fgetc() except that it may be implemented as a macro which evaluates stream more
than once.
getchar() is equivalent to getc(stdin).
gets() reads a line from stdin into the buffer pointed to by s until either a terminating newline or EOF,
which it replaces with ’\0’.Nocheck for buffer overrun is performed (see BUGS below).
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to
by s.Reading stops after an EOF or a newline. If anewline is read, it is stored into the buffer.A’\0’ is
stored after the last character in the buffer.
ungetc() pushes c back to stream,cast to unsigned char,where it is available for subsequent read opera-
tions. Pushed-back characters will be returned in reverse order; only one pushback is guaranteed.
Calls to the functions described here can be mixed with each other and with calls to other input functions
from the stdio library for the same input stream.
Fornon-locking counterparts, see unlocked_stdio(3).
RETURN VALUE
fgetc(), getc() and getchar() return the character read as an unsigned char cast to an int or EOF on end of
file or error.
gets() and fgets() return s on success, and NULL on error or when end of file occurs while no characters
have been read.
ungetc() returns c on success, or EOF on error.
CONFORMING TO
C89, C99. LSB deprecates gets().
BUGS
Neveruse gets(). Because it is impossible to tell without knowing the data in advance howmanycharacters
gets() will read, and because gets() will continue to store characters past the end of the buffer,itis
extremely dangerous to use. It has been used to break computer security.Use fgets() instead.
It is not advisable to mix calls to input functions from the stdio library with low-levelcalls to read() for the
file descriptor associated with the input stream; the results will be undefined and very probably not what
you want.
SEE ALSO
read(2), write(2), ferror(3), fgetwc(3), fgetws(3), fopen(3), fread(3), fseek(3), getline(3), getwchar(3),
puts(3), scanf(3), ungetwc(3), unlocked_stdio(3)
GNU 1993-04-04 1
STRTOK(3) Linux Programmer’sManual STRTOK(3)
NAME
strtok, strtok_r − extract tokens from strings
SYNOPSIS
#include
char *strtok(char *str,const char *delim);
char *strtok_r(char *str,const char *delim,char **saveptr);
DESCRIPTION
The strtok() function parses a string into a sequence of tokens. On the first call to strtok() the string to be
parsed should be specified in str.Ineach subsequent call that should parse the same string, str should be
NULL.
The delim argument specifies a set of characters that delimit the tokens in the parsed string. The caller may
specify different strings in delim in successive calls that parse the same string.
Each call to strtok() returns a pointer to a null-terminated string containing the next token. This string does
not include the delimiting character.Ifnomore tokens are found, strtok() returns NULL.
Asequence of twoormore contiguous delimiter characters in the parsed string is considered to be a single
delimiter.Delimiter characters at the start or end of the string are ignored. Put another way: the tokens
returned by strtok() are always non-empty strings.
The strtok_r() function is a reentrant version strtok(). The saveptr argument is a pointer to a char * vari-
able that is used internally by strtok_r() in order to maintain context between successive calls that parse the
same string.
On the first call to strtok_r(), str should point to the string to be parsed, and the value of saveptr is
ignored. In subsequent calls, str should be NULL, and saveptr should be unchanged since the previous
call.
Different strings may be parsed concurrently using sequences of calls to strtok_r() that specify different
saveptr arguments.
EXAMPLE
The following program uses nested loops that employ strtok_r() to break a string into a two-levelhierarchy
of tokens. The first command-line argument specifies the string to be parsed. The second argument speci-
fies the delimiter character(s) to be used to separate that string into "major" tokens. The third argument
specifies the delimiter character(s) to be used to separate the "major" tokens into subtokens.
#include
#include
#include
int
main(int argc, char *argv[])
{
char *str1, *str2, *token, *subtoken;
char *saveptr1, *saveptr2;
int j;
if (argc != 4) {
fprintf(stderr,"Usage: %s string delim subdelim\n",
argv[0]);
exit(EXIT_FAILURE);
GNU 2000-02-13 1
STRTOK(3) Linux Programmer’sManual STRTOK(3)
}
for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) {
token = strtok_r(str1, argv[2], saveptr1);
if (token == NULL)
break;
printf("%d: %s0, j, token);
for (str2 = token; ; str2 = NULL) {
subtoken = strtok_r(str2, argv[3], saveptr2);
if (subtoken == NULL)
break;
printf(" %s0, subtoken);
}
}
exit(EXIT_SUCCESS);
}/*main */
An example of the output produced by this program is the following:
$./a.out ’a/bbb///cc;xxx:yyy:’ ’:;’ ’/’
1: a/bbb///cc
a
bbb
cc
2: xxx
xxx
3: yyy
yyy
BUGS
Av oid using these functions. If you do use them, note that:
These functions modify their first argument.
These functions cannot be used on constant strings.
The identity of the delimiting character is lost.
The strtok() function uses a static buffer while parsing, so it’snot thread safe. Use strtok_r() if
this matters to you.
RETURN VALUE
The strtok() and strtok_r() functions return a pointer to the next token, or NULL if there are no more
tokens.
CONFORMING TO
strtok()
SVr4, POSIX.1-2001, 4.3BSD, C89.
strtok_r()
POSIX.1-2001
SEE ALSO
index(3), memchr(3), rindex(3), strchr(3), strpbrk(3), strsep(3), strspn(3), strstr(3), wcstok(3)
GNU 2000-02-13 2
FORK(2) Linux Programmer’sManual FORK(2)
NAME
fork − create a child process
SYNOPSIS
#include
#include
pid_t fork(void);
DESCRIPTION
fork() creates a child process that differs from the parent process only in its PID and PPID, and in the fact
that resource utilizations are set to 0. File locks and pending signals are not inherited.
Under Linux, fork() is implemented using copy-on-write pages, so the only penalty that it incurs is the time
and memory required to duplicate the parent’spage tables, and to create a unique task structure for the
child.
RETURN VALUE
On success, the PID of the child process is returned in the parent’sthread of execution, and a 0 is returned
in the child’sthread of execution. On failure, a −1 will be returned in the parent’scontext, no child process
will be created, and errno will be set appropriately.
ERRORS
EAGAIN
fork() cannot allocate sufficient memory to copythe parent’spage tables and allocate a task struc-
ture for the child.
EAGAIN
It was not possible to create a newprocess because the caller’s RLIMIT_NPROC resource limit
wasencountered. Toexceed this limit, the process must have either the CAP_SYS_ADMIN or
the CAP_SYS_RESOURCE capability.
ENOMEM
fork() failed to allocate the necessary kernel structures because memory is tight.
CONFORMING TO
SVr4, 4.3BSD, POSIX.1-2001.
EXAMPLE
See pipe(2) and wait(2).
SEE ALSO
clone(2), execve(2), setrlimit(2), unshare(2), vfork(2), wait(2), capabilities(7)
Linux 2.6.6 2004-05-27 1
EXEC(3) Linux Programmer’sManual EXEC(3)
NAME
execl, execlp, execle, execv,execvp − execute a file
SYNOPSIS
#include
externchar **environ;
int execl(const char * path,const char *arg,...);
int execlp(const char * file,const char *arg,...);
int execle(const char * path,const char *arg,
..., char * const envp[]);
int execv(const char * path,char *const argv[]);
int execvp(const char * file,char *const argv[]);
DESCRIPTION
The exec() family of functions replaces the current process image with a newprocess image. The functions
described in this manual page are front-ends for the function execve(2). (See the manual page for execve()
for detailed information about the replacement of the current process.)
The initial argument for these functions is the pathname of a file which is to be executed.
The const char *arg and subsequent ellipses in the execl(), execlp(), and execle() functions can be thought
of as arg0, arg1,..., argn.Together theydescribe a list of one or more pointers to null-terminated strings
that represent the argument list available to the executed program. The first argument, by convention,
should point to the filename associated with the file being executed. The list of arguments must be termi-
nated by a NULL pointer,and, since these are variadic functions, this pointer must be cast (char *) NULL.
The execv() and execvp() functions provide an array of pointers to null-terminated strings that represent the
argument list available to the newprogram. The first argument, by convention, should point to the filename
associated with the file being executed. The array of pointers must be terminated by a NULL pointer.
The execle() function also specifies the environment of the executed process by following the NULL
pointer that terminates the list of arguments in the parameter list or the pointer to the argv array with an
additional parameter.This additional parameter is an array of pointers to null-terminated strings and must
be terminated by a NULL pointer.The other functions takethe environment for the newprocess image
from the external variable environ in the current process.
Some of these functions have special semantics.
The functions execlp() and execvp() will duplicate the actions of the shell in searching for an executable
file if the specified filename does not contain a slash (/) character.The search path is the path specified in
the environment by the PATH variable. If this variable isn’tspecified, the default path ‘‘:/bin:/usr/bin’’is
used. In addition, certain errors are treated specially.
If permission is denied for a file (the attempted execve() returned EACCES), these functions will continue
searching the rest of the search path. If no other file is found, however, theywill return with the global vari-
able errno set to EACCES.
If the header of a file isn’trecognized (the attempted execve() returned ENOEXEC), these functions will
execute the shell with the path of the file as its first argument. (If this attempt fails, no further searching is
done.)
RETURN VALUE
If anyofthe exec() functions returns, an error will have occurred. The return value is −1, and the global
variable errno will be set to indicate the error.
FILES
/bin/sh
BSD MANPAGE1993-11-29 1
EXEC(3) Linux Programmer’sManual EXEC(3)
ERRORS
All of these functions may fail and set errno for anyofthe errors specified for the library function
execve(2).
SEE ALSO
sh(1), execve(2), fork(2), ptrace(2), fexecve(3), environ(7)
COMPATIBILITY
On some other systems the default path (used when the environment does not contain the variable PATH)
has the current working directory listed after /bin and /usr/bin,asananti-Trojan-horse measure. Linux uses
here the traditional "current directory first" default path.
The behavior. of execlp() and execvp() when errors occur while attempting to execute the file is historic
practice, but has not traditionally been documented and is not specified by the POSIX standard. BSD (and
possibly other systems) do an automatic sleep and retry if ETXTBSY is encountered. Linux treats it as a
hard error and returns immediately.
Traditionally,the functions execlp() and execvp() ignored all errors except for the ones described above
and ENOMEM and E2BIG,upon which theyreturned. Theynow return if anyerror other than the ones
described above occurs.
CONFORMING TO
POSIX.1-2001.
BSD MANPAGE1993-11-29 2
EXECVE(2) Linux Programmer’sManual EXECVE(2)
NAME
execve−execute program
SYNOPSIS
#include
int execve(const char * filename,char *const argv[],
char *const envp[]);
DESCRIPTION
execve() executes the program pointed to by filename. filename must be either a binary executable, or a
script. starting with a line of the form. "#! interpreter [arg]". In the latter case, the interpreter must be a valid
pathname for an executable which is not itself a script, which will be invokedas interpreter [arg] filename.
argv is an array of argument strings passed to the newprogram. envp is an array of strings, conventionally
of the form. key=value,which are passed as environment to the newprogram. Both argv and envp must be
terminated by a null pointer.The argument vector and environment can be accessed by the called pro-
gram’smain function, when it is defined as int main(int argc, char *argv[], char *envp[]).
execve() does not return on success, and the text, data, bss, and stack of the calling process are overwritten
by that of the program loaded. The program invokedinherits the calling process’sPID, and anyopen file
descriptors that are not set to close-on-exec. Signals pending on the calling process are cleared. Anysig-
nals set to be caught by the calling process are reset to their default behaviour.The SIGCHLD signal
(when set to SIG_IGN) may or may not be reset to SIG_DFL.
If the current program is being ptraced, a SIGTRAP is sent to it after a successful execve().
If the set-user-ID bit is set on the program file pointed to by filename,and the calling process is not being
ptraced, then the effective user ID of the calling process is changed to that of the owner of the program file.
iSimilarly,when the set-group-ID bit of the program file is set the effective group ID of the calling process
is set to the group of the program file.
The effective user ID of the process is copied to the savedset-user-ID; similarly,the effective group ID is
copied to the savedset-group-ID. This copying takes place after anyeffective IDchanges that occur
because of the set-user-ID and set-group-ID permission bits.
If the executable is an a.out dynamically-linked binary executable containing shared-library stubs, the
Linux dynamic linker ld.so(8) is called at the start of execution to bring needed shared libraries into mem-
ory and link the executable with them.
If the executable is a dynamically-linked ELF executable, the interpreter named in the PT_INTERP seg-
ment is used to load the needed shared libraries. This interpreter is typically /lib/ld-linux.so.1 for binaries
linked with the Linux libc version 5, or /lib/ld-linux.so.2 for binaries linked with the GNU libc version 2.
RETURN VALUE
On success, execve() does not return, on error −1 is returned, and errno is set appropriately.
ERRORS
E2BIG The total number of bytes in the environment (envp)and argument list (argv)istoo large.
EACCES
Search permission is denied on a component of the path prefix of filename or the name of a script
interpreter.(See also path_resolution(2).)
EACCES
The file or a script. interpreter is not a regular file.
Linux 2.6.7 2004-06-23 1
EXECVE(2) Linux Programmer’sManual EXECVE(2)
EACCES
Execute permission is denied for the file or a script. or ELF interpreter.
EACCES
The file system is mounted noexec.
EFAULT
filename points outside your accessible address space.
EINVAL
An ELF executable had more than one PT_INTERP segment (i.e., tried to name more than one
interpreter).
EIO An I/O error occurred.
EISDIR
An ELF interpreter was a directory.
ELIBBAD
An ELF interpreter was not in a recognised format.
ELOOP
Toomanysymbolic links were encountered in resolving filename or the name of a script. or ELF
interpreter.
EMFILE
The process has the maximum number of files open.
ENAMETOOLONG
filename is too long.
ENFILE
The system limit on the total number of open files has been reached.
ENOENT
The file filename or a script. or ELF interpreter does not exist, or a shared library needed for file or
interpreter cannot be found.
ENOEXEC
An executable is not in a recognised format, is for the wrong architecture, or has some other for-
mat error that means it cannot be executed.
ENOMEM
Insufficient kernel memory was available.
ENOTDIR
Acomponent of the path prefix of filename or a script. or ELF interpreter is not a directory.
EPERM
The file system is mounted nosuid,the user is not the superuser,and the file has an SUID or SGID
bit set.
EPERM
The process is being traced, the user is not the superuser and the file has an SUID or SGID bit set.
ETXTBSY
Executable was open for writing by one or more processes.
CONFORMING TO
SVr4, 4.3BSD, POSIX.1-2001. POSIX.1-2001 does not document the #! behavior. but is otherwise com-
patible.
NOTES
SUID and SGID processes can not be ptrace()d.
Linux ignores the SUID and SGID bits on scripts.
Linux 2.6.7 2004-06-23 2
EXECVE(2) Linux Programmer’sManual EXECVE(2)
The result of mounting a filesystem nosuid vary between Linux kernel versions: some will refuse execution
of SUID/SGID executables when this would give the user powers she did not have already (and return
EPERM), some will just ignore the SUID/SGID bits and exec() successfully.
Amaximum line length of 127 characters is allowed for the first line in a #! executable shell script.

联系我们
  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-21:00
  • 微信:codinghelp
热点标签

联系我们 - QQ: 99515681 微信:codinghelp
程序辅导网!