1、Linux操作系统实验报告姓名: 杨子坤 学号: 0938115 班级:09级通信2班 实验三 普通文件和目录编程1、编写程序mycp.c,实现从命令行读入文件的复制功能,用原始文件系统调用。程序流程如下:程序源代码如下:/mycp.c/#include#include#include#define PERMS 0666/默认权限main(int argc,char *argv)int f1,f2,n;char bufBUFSIZ;if(argc!=3)/参数个数不正确 printf(Usage:cp from ton);if(f1=open(argv1,O_RDONLY,0)=-1)/只读打
2、开待复制文件 printf(cp:cannot open %sn,argv1);if(f2=creat(argv2,PERMS)=-1)/创建目标文件,权限读写 printf(cp:cannot creat %s,mode %03on,argv2,PERMS);while(n=read(f1,buf,BUFSIZ)0)/读取文件 if(write(f2,buf,n)!=n)/写入文件printf(cp:write error on file %sn,argv2);return 0;运行结果:kurykuryyang-Y471A /expt/expt3 $ gcc -o mycp mycp.ck
3、urykuryyang-Y471A /expt/expt3 $ lsfile1 mycat.c mycatf.c mycp mycp.c mycpf.c myls.c newfile.c 实验3.vsdkurykuryyang-Y471A /expt/expt3 $ ./mycp file1 filenewkurykuryyang-Y471A /expt/expt3 $ lsfile1 mycat.c mycp mycpf.c newfile.c filenew mycatf.c mycp.c myls.c 实验3.vsdkurykuryyang-Y471A /expt/expt3 $ cat
4、 file1hello the worldkurykuryyang-Y471A /expt/expt3 $ cat filenewhello the world可见在终端中用./mycp file1 filenew实现了把文件file1复制到文件filenew的功能,和cp命令所实现的功能一样。2、编写程序mycat.c,实现文件内容的显示,用原始文件系统调用实现。程序流程如下:程序源代码如下:/mycat.c/#include#includemain(int argc,char *argv)int f1,n;char bufBUFSIZ;/存放读取的信息if(argc=1|argc2)/输入
5、参数个数不正确 printf(enter the right file namen); exit(0); else if(f1=open(argv1,O_RDONLY,0)=-1)/打开文件 printf(cat:cannot open %sn,argv1);while(n=read(f1,buf,BUFSIZ)0)/读文件 puts(buf);/输出读取的长度运行结果:在终端中运行命令./mycat file1输出file1的内容kurykuryyang-Y471A /expt/expt3 $ gcc -o mycat mycat.ckurykuryyang-Y471A /expt/expt
6、3 $ ./mycat file1hello the world3、用流文件系统重新编写上面的程序。(1)用流文件系统重新编写程序mycpf.c,实现从命令行读入文件的复制功能。程序流程如下:程序源代码如下:/mycpf.c/#include#include#includemain(int argc,char *argv)FILE*fp1,*fp2;char ch;if(argc=1)/输入参数个数不正确 printf(have not enter file name,press any key exitn); getchar();/输入一个字符,缓冲 exit(0);if(fp1=fopen
7、(argv1,r)=NULL)/只读方式打开待复制的文件 printf(Cannot open %sn,argv1); getchar(); exit(1);if(argc=2)/参数不正确缺少目标文件 printf(have not enter dest file name,press any key exitn); getchar(); exit(0);else if(fp2=fopen(argv2,w+)=NULL)/创建目标文件,读写允许 printf(Cannot open %sn,argv2); getchar(); exit(1);while(ch=fgetc(fp1)!=EOF
8、)/读取文件内容fputc(ch,fp2);/输出文件内容fclose(fp1);/关闭文件fclose(fp2);运行结果:kurykuryyang-Y471A /expt/expt3 $ gcc -o mycpf mycpf.ckurykuryyang-Y471A /expt/expt3 $ lsfile3 mycat.c mycp mycpf myls.c 实验3.vsd mycat mycatf.c mycp.c mycpf.c newfile.ckurykuryyang-Y471A /expt/expt3 $ ./mycpf file3 filenew1kurykuryyang-Y4
9、71A /expt/expt3 $ lsfile3 mycat mycatf.c mycp.c mycpf.c newfile.c filenew1 mycat.c mycp mycpf myls.kurykuryyang-Y471A /expt/expt3 $ cat file3this is a demokurykuryyang-Y471A /expt/expt3 $ cat filenew1this is a demo(2)用流文件系统重新编写程序mycatf.c,实现文件内容的显示。程序流程如下:程序源代码如下:/mycatf.c/#include#include#includemai
10、n(int argc,char *argv) FILE *fp; char ch; if(argc!=2) printf(please enter legal file namen); exit(0); else if(fp=fopen(argv1,r)=NULL)/打开文件 printf(Cannot open %sn,argv1); getchar();/暂停,输入一个字符 exit(1); ch=fgetc(fp);/读文件 while(ch!=EOF) putchar(ch);/如果不为结尾则输出文件内容 ch=fgetc(fp);fclose(fp);运行结果:kurykuryyan
11、g-Y471A /expt/expt3 $ gcc -o mycatf mycatf.ckurykuryyang-Y471A /expt/expt3 $ ./mycatf file3this is a demokurykuryyang-Y471A /expt/expt3 $ cat file3this is a demo4、调用目录函数,编写程序myls.c,实现按下面格式显示当前目录文件列表:文件名文件大小文件创建时间注意研究文件创建时间的转换,以及asctime()函数和ctime()函数的用法。程序流程如下:程序源代码如下:/myls.c/#include#include#include
12、#include#include#include #include #includeint main()DIR *dp;struct dirent *ep;/目录操作struct stat st;/文件目录操作符号相关dp=opendir(./);/打开当前目录if(dp!=NULL)while(ep=readdir(dp)/目录非空if(stat(ep-d_name,&st) != -1)/目录下文件名读取print_file_info(ep,st);/自定义返回信息的函数closedir(dp);elseputs(Couldnt open the directory.n);return 0
13、;int print_file_info(struct dirent *ep,struct stat st)/结构体作为参数printf(%s,ep-d_name);/输出文件名printf( );printf(%ld,st.st_size);/输出文件大小(字节)printf( );char str50;strcpy(str,ctime(&(st.st_mtime);/数组保存创建时间strstrlen(str)-1 = ;printf(%s,str);putchar(n);return 0;运行结果:kurykuryyang-Y471A /expt/expt3 $ gcc -o myls
14、myls.ckurykuryyang-Y471A /expt/expt3 $ ./mylsmyls.c 1125 Sun Dec 25 23:12:24 2011 myls 7591 Sun Dec 25 23:09:58 2011 mycpf.c 916 Sun Dec 25 23:03:32 2011 . 4096 Sun Dec 25 23:12:15 2011 mycatf.c 604 Sun Dec 25 23:07:56 2011 mycp.c 729 Sun Dec 25 22:50:41 2011 . 4096 Sun Dec 25 23:12:24 2011 mycat.c
15、527 Sun Dec 25 22:55:41 2011 kurykuryyang-Y471A /expt/expt3 $ ls -l总用量 28-rw- 1 kury kury 527 2011-12-25 22:55 mycat.c-rw- 1 kury kury 604 2011-12-25 23:07 mycatf.c-rw- 1 kury kury 729 2011-12-25 22:50 mycp.c-rw- 1 kury kury 916 2011-12-25 23:03 mycpf.c-rwxrwxr-x 1 kury kury 7591 2011-12-25 23:09 my
16、ls-rw- 1 kury kury 1125 2011-12-25 23:12 myls.c可见程序myls能够实现和命令ls l相似的功能,输出了文件名称、文件大小和创建时间。实验四 进程实验1、编写程序,显示所有环境变量的名称和值。程序流程如下:程序源代码如下:/disp.c/#include#includeextern char*environ;/声明environ,包含全部环境变量int main() char *var; for(var=environ;*var!=NULL;+var)/非结尾则输出printf(%sn,*var); return 0;运行结果:kurykuryya
17、ng-Y471A /expt/expt4 $ gcc -o disp disp.ckurykuryyang-Y471A /expt/expt4 $ ./dispSSH_AGENT_PID=1695GPG_AGENT_INFO=/tmp/keyring-3oBkz7/gpg:0:1TERM=xtermSHELL=/bin/bashXDG_SESSION_COOKIE=c45faa0e8077e59244872ea40000000c-1324827323.847396-1717228196WINDOWID=54525956GNOME_KEYRING_CONTROL=/tmp/keyring-3oB
18、kz7GTK_MODULES=canberra-gtk-module:canberra-gtk-moduleUSER=kuryLIBGL_DRIVERS_PATH=/usr/lib/fglrx/driXDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0SSH_AUTH_SOCK=/tmp/keyring-3oBkz7/sshUSERNAME=kuryDEFAULTS_PATH=/usr/share/gconf/gnome-shell
19、.default.pathSESSION_MANAGER=local/kuryyang-Y471A:/tmp/.ICE-unix/1641,unix/kuryyang-Y471A:/tmp/.ICE-unix/1641XDG_CONFIG_DIRS=/etc/xdg/xdg-gnome-shell:/etc/xdgPATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/gamesDESKTOP_SESSION=gnome-shellLC_MESSAGES=zh
20、_CN.UTF-8QT_IM_MODULE=ximLC_COLLATE=zh_CN.UTF-8PWD=/home/kury/expt/expt4XMODIFIERS=im=ibusGNOME_KEYRING_PID=1630LANG=zh_CN.UTF-8MANDATORY_PATH=/usr/share/gconf/gnome-shell.mandatory.pathGDMSESSION=gnome-shellSHLVL=1HOME=/home/kuryLANGUAGE=zh_CN:enGNOME_DESKTOP_SESSION_ID=this-is-deprecatedLOGNAME=ku
21、ryXDG_DATA_DIRS=/usr/share/gnome-shell:/usr/share/gnome:/usr/local/share/:/usr/share/DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-cg20lZ5Qfe,guid=d4da4f5a736bef065010f00a0000002bLC_CTYPE=zh_CN.UTF-8DISPLAY=:0.0XDG_CURRENT_DESKTOP=GNOMEGTK_IM_MODULE=ximCOLORTERM=gnome-terminalXAUTHORITY=/home/kur
22、y/.Xauthority_=./dispOLDPWD=/home/kury/expt如上,程序列出了所有的环境变量。*2、编写程序,模仿讲义上的mysystem程序,实现输入命令的执行。程序流程如下:程序源代码如下:/mysystem.c/实现输入命令的执行,命令长度超过一个字符串就用 xxx#include#include#include#include#include#include#define SHELL /bin/shint mysystem(const char*command)int status;pid_t pid;pid=fork();if(pid=0) /子进程,执行命令
23、 execl(SHELL,SHELL,-c,command,NULL);_exit(EXIT_FAILURE); else if(pid0)/创建子进程失败status=-1;else if(waitpid(pid,&status,0)!=pid)/等待子进程结束 status=-1;return status;int main(int argc,char *argv)mysystem(argv1);/第二个参数为命令return 0;运行结果:kurykuryyang-Y471A /expt/expt4 $ gcc -o mysystem mysystem.ckurykuryyang-Y47
24、1A /expt/expt4 $ ./mysystem lsdisp.cmysystem mysystem.ckurykuryyang-Y471A /expt/expt4 $ ./mysystem pwd/home/kury/expt/expt4kurykuryyang-Y471A /expt/expt4 $ ./mysystem ls -a. . disp.c mysystem mysystem.c实验五 命名管道实验1、研究mkfifo命令,在当前目录下创建一个myfifo的命名管道。在终端中的运行结果:kurykuryyang-Y471A /expt/expt5 $ mkfifo -he
25、lp用法:mkfifo 选项. 名称.以指定的名称创建先进先出文件(FIFO)。长选项必须使用的参数对于短选项时也是必需使用的。 -m, -mode=模式 设置权限模式(类似chmod),而不是rwxrwxrwx 减umask -Z, -context=CTX 将每个创建的目录的SELinux 安全环境设置为CTX -help显示此帮助信息并退出 -version显示版本信息并退出kurykuryyang-Y471A /expt/expt5 $ lsmkfifo.c server1.c server.ckurykuryyang-Y471A /expt/expt5 $ mkfifo myfifo
26、kurykuryyang-Y471A /expt/expt5 $ mkfifo myfifo1 -m777kurykuryyang-Y471A /expt/expt5 $ lsmkfifo.c myfifo myfifo1 server1.c server.c2、用mkfifo()函数实现相同的功能。程序流程如下:程序源代码如下:/mkfifo.c/#include#include#include#define FIFO ./fifo_channel/当前目录下创建管道int main(int argc,char* argv) int d; d=mkfifo(FIFO,0777);/创建管道
27、if(d=-1)perror(cannot creat FIFO channeln);return 1; return 0;运行结果:kurykuryyang-Y471A /expt/expt5 $ lsmkfifo.c server1.c server.ckurykuryyang-Y471A /expt/expt5 $ gcc -o mkfifo mkfifo.ckurykuryyang-Y471A /expt/expt5 $ ./mkfifokurykuryyang-Y471A /expt/expt5 $ lsfifo_channel mkfifo mkfifo.c server1.c s
28、erver.c3、编写一个服务器程序server.c,实现从管道myfifo中读取内容,并在终端中显示出来。打开命令行终端,运行server,然后打开另一个命令行终端,使用“cp 文件1 myfifo”命令把文件1的内容输出到myfifo,测试server的功能。程序流程如下:程序源代码如下:/server.c/#include#include#include#include#define FIFO ./FIFO_channel1/默认管道int main(int argc,char* argv) int fd,d; char bufferBUFSIZ; unlink(FIFO);/删除已经存
29、在的管道 d=mkfifo(FIFO,0666);/创建FIFO管道 if(d=-1)perror(cannot creat FIFO channeln);return 1; fd=open(FIFO,O_RDONLY);/打开管道 if(fd=-1)perror(cannot open the FIFO);/从管道读取信息 if(read(fd,buffer,BUFSIZ)=-1)perror(process cannot read data from FIFO);return 1; elseprintf(Receive message from FIFO:n%s,buffer);/收到信息
30、 return 0;运行结果:kurykuryyang-Y471A /expt/expt5 $ gcc -o server server.ckurykuryyang-Y471A /expt/expt5 $ ./server另一终端执行kurykuryyang-Y471A /expt/expt5 $ cp hello FIFO_channel1kurykuryyang-Y471A /expt/expt5 $ ./serverReceive message from FIFO:hello the world4、编写客户机程序,实现把指定文件输出到myfifo的功能,从而实现和服务器程序的通信。测试
31、该程序的功能。程序流程如下:程序源代码如下:/server1.c/向管道中写入数据,在另一个进程中读取信息测试/#include#include#include#include#define FIFO ./FIFO_channel1int main(int argc,char* argv)int fd,fd1;int count;char bufferBUFSIZ;if(argc!=2) printf(Command: %s filenamen,argv0); return 1;/打开命名管道写入数据fd=open(FIFO,O_WRONLY);if(fd=-1) perror(cannot
32、open the FIFO);/打开要写入的文件if(fd1=open(argv1,O_RDONLY)=-1) perror(cannot open the filen); return 1;count=read(fd1,buffer,BUFSIZ);/向管道中写入数据if(write(fd,buffer,BUFSIZ)=-1) perror(process cannot write data to FIFO); return 1;else printf(send message: n%s,buffer);return 0;运行结果:在当前终端下:kurykuryyang-Y471A /exp
33、t/expt5 $ mkfifo FIFO_channel1kurykuryyang-Y471A /expt/expt5 $ gcc -o server1 server1.ckurykuryyang-Y471A /expt/expt5 $ ./server1 hello另一终端下:kurykuryyang-Y471A /expt/expt5 $ ./serverReceive message from FIFO:hello the world当前终端:kurykuryyang-Y471A /expt/expt5 $ ./server1 hellosend message: hello the
34、world由于第一个程序server.c存在缺陷,没有信号进入管道的时候,管道阻塞从而不能读取,所以只有在打开server.c程序之后再运行server1.c写管道,才能读,从而返回正确的发送结果。实验六 信号实验1、研究kill命令,掌握通过kill命令发送信号的方法。在终端中运行结果:kurykuryyang-Y471A /expt/expt6 $ ps a PID TTY STAT TIME COMMAND 1149 tty4 Ss+ 0:00 /sbin/getty -8 38400 tty4 1152 tty5 Ss+ 0:00 /sbin/getty -8 38400 tty5 1
35、162 tty2 Ss+ 0:00 /sbin/getty -8 38400 tty2 1163 tty3 Ss+ 0:00 /sbin/getty -8 38400 tty3 1165 tty6 Ss+ 0:00 /sbin/getty -8 38400 tty6 1197 tty7 Rs+ 0:09 /usr/bin/X :0 -auth /var/run/lightdm/root/:0 -noliste 1520 tty1 Ss+ 0:00 /sbin/getty -8 38400 tty1 2101 pts/0 Ss 0:00 bash 2181 pts/1 Ss+ 0:00 bash
36、 2232 pts/0 R+ 0:00 ps akurykuryyang-Y471A /expt/expt6 $ kill -9 2181kurykuryyang-Y471A /expt/expt6 $ ps a PID TTY STAT TIME COMMAND 1149 tty4 Ss+ 0:00 /sbin/getty -8 38400 tty4 1152 tty5 Ss+ 0:00 /sbin/getty -8 38400 tty5 1162 tty2 Ss+ 0:00 /sbin/getty -8 38400 tty2 1163 tty3 Ss+ 0:00 /sbin/getty -
37、8 38400 tty3 1165 tty6 Ss+ 0:00 /sbin/getty -8 38400 tty6 1197 tty7 Rs+ 0:09 /usr/bin/X :0 -auth /var/run/lightdm/root/:0 -noliste 1520 tty1 Ss+ 0:00 /sbin/getty -8 38400 tty1 2101 pts/0 Ss 0:00 bash 2233 pts/0 R+ 0:00 ps a可以看出,使用kill命令把进程号为2181的一个bash进程杀死了。2、编写程序,通过定义信号处理函数来截获user消息。在消息处理函数中,设置标志变量
38、,测主程序中通过系统调用pause()等待消息,如果消息是user,则在终端上显示消息。打开命令行窗口,运行这个程序。程序流程如下:程序源代码如下:/getmysig.c/#include#include#include#includevolatile sig_atomic_t m =0;/消息标志位void sigusr(int signal)m=1;printf(Got the SIGUSR1 signal.n);printf(The label is:%dn,m);exit(0);int main(void)if(signal(SIGUSR1,sigusr)=SIG_ERR)/信号处理
39、perror(cannot reset the SIGUSR1 signal handler); return 1;printf(Waitting signal from user.n);printf(The label is:%dn,m);pause();/等待消息信号return 0;运行结果:kurykuryyang-Y471A /expt/expt6 $ gcc -o getmysig getmysig.ckurykuryyang-Y471A /expt/expt6 $ ./getmysigWaitting signal from user.The label is:0可以看出,该进程没有接收到消息信号的时候在等待状态,打印出标志位为原始值。3、打开命令行窗口,通过ps命令获得2中程序的进程号,用kill命令给该进程发送user消息,观察其输出运行结果:终端2:kurykuryyang-Y471A $ ps a PID TTY STAT TIME COMMAND 1149 tty4 Ss+ 0:00 /sbin/getty -8 38400 tty4 1152 tty5 Ss+ 0:00 /sbin/gett