首页 > 代码库 > 20145225 《信息安全系统设计基础》第11周学习总结
20145225 《信息安全系统设计基础》第11周学习总结
exec1
代码如下:
1 #include <stdio.h> 2 #include <unistd.h> 3 int main(){ 4 char *arglist[3]; 5 arglist[0] = "ls"; 6 arglist[1] = "-l"; 7 arglist[2] = 0 ; 8 printf("* * * About to exec ls -l\n"); 9 execvp( arglist[0] , arglist ); 10 printf("* * * ls is done. bye\n"); 11 }
可以看到这个代码中用了execvp函数。
表头文件:
#include<unistd.h>
定义函数:
int execvp(const char file ,char const argv []);
execvp()会从PATH 环境变量所指的目录中查找符合参数file 的文件名,找到后便执行该文件,然后将第二个参数argv传给该欲执行的文件。
如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno中。
所以运行结果如下:
可以看到,exevp函数调用成功没有返回,所以没有打印出“* * * ls is done. bye”这句话。
exec2
1 #include <stdio.h> 2 #include <unistd.h> 3 4 int main() 5 { 6 char *arglist[3]; 7 char*myenv[3]; 8 myenv[0] = "PATH=:/bin:"; 9 myenv[1] = NULL; 10 11 arglist[0] = "ls"; 12 arglist[1] = "-l"; 13 arglist[2] = 0 ; 14 printf("* * * About to exec ls -l\n"); 15 16 execlp("ls", "ls", "-l", NULL); 17 printf("* * * ls is done. bye\n");
它与exec1的区别就在于exevp函数的第一个参数,exec1传的是ls,exec2直接用的arglist[0],不过由定义可得这两个等价,所以运行结果是相同的。
exec3
代码如下:
1 #include <stdio.h> 2 #include <unistd.h> 3 4 int main() 5 { 6 char *arglist[3]; 7 char*myenv[3]; 8 myenv[0] = "PATH=:/bin:"; 9 myenv[1] = NULL; 10 11 arglist[0] = "ls"; 12 arglist[1] = "-l"; 13 arglist[2] = 0 ; 14 printf("* * * About to exec ls -l\n"); 15 16 execlp("ls", "ls", "-l", NULL); 17 printf("* * * ls is done. bye\n"); 18 }
这个代码里使用了execlp函数,用法如下:
头文件:
#include<unistd.h>
定义函数:
int execlp(const char * file,const char * arg,....);
函数说明:
execlp()会从PATH 环境变量所指的目录中查找符合参数file的文件名,找到后便执行该文件,然后将第二个以后的参数当做该文件的argv[0]、argv[1]……,最后一个参数必须用空指针(NULL)作结束。如果用常数0来表示一个空指针,则必须将它强制转换为一个字符指针,否则将它解释为整形参数,如果一个整形数的长度与char * 的长度不同,那么exec函数的实际参数就将出错。如果函数调用成功,进程自己的执行代码就会变成加载程序的代码,execlp()后边的代码也就不会执行了.
返回值:
如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno 中。
也就是说,这个代码指定了环境变量,然后依然执行了ls -l指令,成功后没有返回,所以最后一句话不会输出。运行结果同exec1.
forkdemo1
代码如下:
1 #include <stdio.h> 2 #include<sys/types.h> 3 #include<unistd.h> 4 int main() 5 { 6 int ret_from_fork, mypid; 7 mypid = getpid(); 8 printf("Before: my pid is %d\n", mypid); 9 ret_from_fork = fork(); 10 sleep(1); 11 printf("After: my pid is %d, fork() said %d\n", 12 getpid(), ret_from_fork); 13 14 return 0; 15 }
代码解释:
这个代码先是打印进程pid,然后调用fork函数生成子进程,休眠一秒后再次打印进程id,这时父进程打印子进程pid,子进程返回0.
运行结果如下:
forkdemo2
代码如下:
1 #include <stdio.h> 2 #include <unistd.h> 3 4 int main() 5 { 6 printf("before:my pid is %d\n", getpid() ); 7 fork(); 8 fork(); 9 printf("aftre:my pid is %d\n", getpid() ); 10 11 return 0; 12 }
这个代码调用两次fork,一共产生四个子进程,所以会打印四个aftre输出。
结果如图:
forkdemo3
代码如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 5 int main() 6 { 7 int fork_rv; 8 9 printf("Before: my pid is %d\n", getpid()); 10 11 fork_rv = fork(); /* create new process */ 12 13 if ( fork_rv == -1 ) /* check for error */ 14 perror("fork"); 15 else if ( fork_rv == 0 ){ 16 printf("I am the child. my pid=%d\n", getpid()); 17 18 exit(0); 19 } 20 else{ 21 printf("I am the parent. my child is %d\n", fork_rv); 22 exit(0); 23 } 24 25 return 0; 26 }
fork产生子进程,父进程返回子进程pid,不为0,所以输出父进程的那句话,子进程返回0,所以会输出子进程那句话。
结果如下:
forkdemo4
代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 5 int main() 6 { 7 int fork_rv; 8 9 printf("Before: my pid is %d\n", getpid()); 10 11 fork_rv = fork(); /* create new process */ 12 13 if ( fork_rv == -1 ) /* check for error */ 14 perror("fork"); 15 16 else if ( fork_rv == 0 ){ 17 printf("I am the child. my pid=%d\n", getpid()); 18 printf("parent pid= %d, my pid=%d\n", getppid(), getpid()); 19 exit(0); 20 } 21 22 else{ 23 printf("I am the parent. my child is %d\n", fork_rv); 24 sleep(10); 25 exit(0); 26 } 27 28 return 0; 29 }
先打印进程pid,然后fork创建子进程,父进程返回子进程pid,所以输出parent一句,休眠十秒;子进程返回0,所以输出child与之后一句。
运行结果如下:
forkgdb
代码如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 5 int gi=0; 6 int main() 7 { 8 int li=0; 9 static int si=0; 10 int i=0; 11 12 pid_t pid = fork(); 13 if(pid == -1){ 14 exit(-1); 15 } 16 else if(pid == 0){ 17 for(i=0; i<5; i++){ 18 printf("child li:%d\n", li++); 19 sleep(1); 20 printf("child gi:%d\n", gi++); 21 printf("child si:%d\n", si++); 22 } 23 exit(0); 24 25 } 26 else{ 27 for(i=0; i<5; i++){ 28 printf("parent li:%d\n", li++); 29 printf("parent gi:%d\n", gi++); 30 sleep(1); 31 printf("parent si:%d\n", si++); 32 } 33 exit(0); 34 35 } 36 return 0; 37 }
显示结果如下:
这个的主要区别是在,父进程打印是先打印两句,然后休眠一秒,然后打印一句,子进程先打印一句,然后休眠一秒,然后打印两句。并且这两个线程是并发的,所以可以看到在一个线程休眠的那一秒,另一个线程在执行,并且线程之间相互独立互不干扰。
psh1
代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <unistd.h> 5 6 #define MAXARGS 20 7 #define ARGLEN 100 8 9 int execute( char *arglist[] ) 10 { 11 execvp(arglist[0], arglist); 12 perror("execvp failed"); 13 exit(1); 14 } 15 16 char * makestring( char *buf ) 17 { 18 char *cp; 19 20 buf[strlen(buf)-1] = ‘\0‘; 21 cp = malloc( strlen(buf)+1 ); 22 if ( cp == NULL ){ 23 fprintf(stderr,"no memory\n"); 24 exit(1); 25 } 26 strcpy(cp, buf); 27 return cp; 28 } 29 30 int main() 31 { 32 char *arglist[MAXARGS+1]; 33 int numargs; 34 char argbuf[ARGLEN]; 35 36 numargs = 0; 37 while ( numargs < MAXARGS ) 38 { 39 printf("Arg[%d]? ", numargs); 40 if ( fgets(argbuf, ARGLEN, stdin) && *argbuf != ‘\n‘ ) 41 arglist[numargs++] = makestring(argbuf); 42 else 43 { 44 if ( numargs > 0 ){ 45 arglist[numargs]=NULL; 46 execute( arglist ); 47 numargs = 0; 48 } 49 } 50 } 51 return 0; 52 }
这个代码就相当于你输入要执行的指令,回车表示输入结束,然后输入的每个参数对应到函数中,再调用对应的指令。
结果:
psh2
代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <sys/types.h> 5 #include <sys/wait.h> 6 #include <unistd.h> 7 #include <signal.h> 8 9 #define MAXARGS 20 10 #define ARGLEN 100 11 12 char *makestring( char *buf ) 13 { 14 char *cp; 15 16 buf[strlen(buf)-1] = ‘\0‘; 17 cp = malloc( strlen(buf)+1 ); 18 if ( cp == NULL ){ 19 fprintf(stderr,"no memory\n"); 20 exit(1); 21 } 22 strcpy(cp, buf); 23 return cp; 24 } 25 26 void execute( char *arglist[] ) 27 { 28 int pid,exitstatus; 29 30 pid = fork(); 31 switch( pid ){ 32 case -1: 33 perror("fork failed"); 34 exit(1); 35 case 0: 36 execvp(arglist[0], arglist); 37 perror("execvp failed"); 38 exit(1); 39 default: 40 while( wait(&exitstatus) != pid ) 41 ; 42 printf("child exited with status %d,%d\n", 43 exitstatus>>8, exitstatus&0377); 44 } 45 } 46 47 int main() 48 { 49 char *arglist[MAXARGS+1]; 50 int numargs; 51 char argbuf[ARGLEN]; 52 53 numargs = 0; 54 while ( numargs < MAXARGS ) 55 { 56 printf("Arg[%d]? ", numargs); 57 if ( fgets(argbuf, ARGLEN, stdin) && *argbuf != ‘\n‘ ) 58 arglist[numargs++] = makestring(argbuf); 59 else 60 { 61 if ( numargs > 0 ){ 62 arglist[numargs]=NULL; 63 execute( arglist ); 64 numargs = 0; 65 } 66 } 67 } 68 return 0; 69 }
比起1来,多了循环判断,不退出的话就会一直要你输入指令,并且对于子程序存在的状态条件。
结果如下:
testbuf
testbuf1:
1 #include <stdio.h> 2 #include <stdlib.h> 3 int main() 4 { 5 printf("hello"); 6 fflush(stdout); 7 while(1); 8 }
效果是先输出hello,然后换行。之后不退出。
testbuf2
1 #include <stdio.h> 2 int main() 3 { 4 printf("hello\n"); 5 while(1); 6 }
效果同上。
可知:fflush(stdout)的效果和换行符\n是一样的。
testpid
1 #include <stdio.h> 2 #include <unistd.h> 3 4 #include <sys/types.h> 5 6 int main() 7 { 8 printf("my pid: %d \n", getpid()); 9 printf("my parent‘s pid: %d \n", getppid()); 10 return 0; 11 }
输出当前进程pid和当前进程的父进程的pid。
testpp
1 #include <stdio.h> 2 #include <stdlib.h> 3 int main() 4 { 5 char **pp; 6 pp[0] = malloc(20); 7 8 return 0; 9 }
这个结果:
testsystem
#include <stdlib.h>
int main ( int argc, char *argv[] )
{
system(argv[1]);
system(argv[2]);
return EXIT_SUCCESS;
} /* ---------- end of function main ---------- */
system()——执行shell命令,也就是向dos发送一条指令。这里是后面可以跟两个参数,然后向dos发送这两个命令,分别执行。如下图,输入ls和dir两个指令后,可以看到分别执行了。
waitdemo1
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <sys/types.h> 4 #include <sys/wait.h> 5 #include <unistd.h> 6 7 #define DELAY 4 8 9 void child_code(int delay) 10 { 11 printf("child %d here. will sleep for %d seconds\n", getpid(), delay); 12 sleep(delay); 13 printf("child done. about to exit\n"); 14 exit(17); 15 } 16 17 void parent_code(int childpid) 18 { 19 int wait_rv=0; /* return value from wait() */ 20 wait_rv = wait(NULL); 21 printf("done waiting for %d. Wait returned: %d\n", 22 childpid, wait_rv); 23 } 24 int main() 25 { 26 int newpid; 27 printf("before: mypid is %d\n", getpid()); 28 if ( (newpid = fork()) == -1 ) 29 perror("fork"); 30 else if ( newpid == 0 ) 31 child_code(DELAY); 32 else 33 parent_code(newpid); 34 35 return 0; 36 }
如果有子进程,则终止子进程,成功返回子进程pid。结果如下图:
waitdemo2
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <sys/types.h> 4 #include <sys/wait.h> 5 #include <unistd.h> 6 7 #define DELAY 10 8 9 void child_code(int delay) 10 { 11 printf("child %d here. will sleep for %d seconds\n", getpid(), delay); 12 sleep(delay); 13 printf("child done. about to exit\n"); 14 exit(27); 15 } 16 17 void parent_code(int childpid) 18 { 19 int wait_rv; 20 int child_status; 21 int high_8, low_7, bit_7; 22 23 wait_rv = wait(&child_status); 24 printf("done waiting for %d. Wait returned: %d\n", childpid, wait_rv); 25 26 high_8 = child_status >> 8; /* 1111 1111 0000 0000 */ 27 low_7 = child_status & 0x7F; /* 0000 0000 0111 1111 */ 28 bit_7 = child_status & 0x80; /* 0000 0000 1000 0000 */ 29 printf("status: exit=%d, sig=%d, core=%d\n", high_8, low_7, bit_7); 30 } 31 32 int main() 33 { 34 int newpid; 35 36 printf("before: mypid is %d\n", getpid()); 37 38 if ( (newpid = fork()) == -1 ) 39 perror("fork"); 40 else if ( newpid == 0 ) 41 child_code(DELAY); 42 else 43 parent_code(newpid); 44 }
这个比起1来就是多了一个子进程的状态区分,把状态拆分成三块,exit,sig和core。具体运行如下:
代码托管
20145225 《信息安全系统设计基础》第11周学习总结