20145312 《信息安全系统设计基础》第12周学习总结

20145312 《信息安全系统设计基础》第12周学习总结

代码总结

ls命令

  • ls功能:读取文件名和文件属性,按照字典序排序后输出。
  • 常用的命令行选项:
ls -l   以长格式的形式查看当前目录下所有可见文件的详细属性
ls -a   列出的内容包含以“.”开头的文件
ls -lu  最后访问时间
ls -s   以块为单位的文件大小
ls -t   按时间排序
ls -F   显示文件类型

ls -l

  • ls -l 的输出每行都包含7个字段
模式              每行的第一个字符表示文件类型,“-”代表普通文件,“d”代表目录文件。
链接数            指该文件被引用的次数
文件所有者        指出文件所有者的用户名
组                指出文件所有者所在的组
大小              显示文件的字节数
最后修改时间      文件的最后修改时间
文件名            文件名
  • ls -l可以显示当前目录下目录或文件的详细属性信息

cp命令

  • 查看帮助文档man cp
  • cp的作用就是读取一个文件的内容到存储器,在新的地址创建空白文件,再从存储器将内容写入新文件。(如下图把ls1.c复制,存为lc.c文件)

ls1和ls2

  • ls1程序的作用是在当前目录显示文件名(未带参数直接显示,带参数的存入argc)
  • ls2不仅显示了文件名,还用来显示文件的详细信息,比如用户名、群组名、大小、创建时间、读写权限等。

echostate.c和setecho.c

echostate.c

  • 功能:查看在命令行中输入命令时是否可见,可见返回1,否则返回0

setecho.c

  • 设置回显位的状态,命令行参数为y则开启,否则关闭。
  • 标准输入的文件描述符为0.
  • 使用tcgetattr()函数和termios结构体可获得标准输入的属性。
  • 使用tcsetattr()函数和termios结构体可以将更改后的属性设置重新写回标准输入。

ioctl函数

  • ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。
  • ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支持,用户就可以在用户程序中使用ioctl函数控制设备的I/O通道。
  • 查看帮助文档man isatty man ioctl
  • isatty:判断一个文件描述符是否指向一个终端
  • ioctl:控制驱动器
  • 程序运行结果

filesize

  • filesize代码用st_size成员来计算文件的字节数大小,gcc后有一个警告,调用正常。

fileinfo

  • fileinfo代码这个功能用来实现显示文件信息,建立了一个stat数据结构。先判断命令是否有操作数,有的话才能继续进行下去,如果没有报错就打印出来相关文件信息,报错就用perror将报错信息打印出来。

spwd命令

  • spwd的功能是列出当前目录。

who命令

  • 这个代码的思想是,从UTMP_FILE文件中读取想要的信息到存储器中,然后再用标准输出函数打印到屏幕上,最后关闭文件。
    -程序运行结果

exec1

  • 代码如下:
#include <stdio.h>
#include <unistd.h>

int main()
{
    char    *arglist[3];

    arglist[0] = "ls";
    arglist[1] = "-l";
    arglist[2] = 0 ;//NULL
    printf("* * * About to exec ls -l\n");
    execvp( "ls" , arglist );
    printf("* * * ls is done. bye");

    return 0;
}
  • 可以看到这个代码中用了execvp函数。

  • 表头文件:#include<unistd.h>

  • 定义函数:int execvp(const char file ,char const argv []);

  • execvp()会从PATH 环境变量所指的目录中查找符合参数file 的文件名,找到后便执行该文件,然后将第二个参数argv传给该欲执行的文件。
    如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno中。

运行结果如下:

exec2

  • 它与exec1的区别就在于exevp函数的第一个参数,exec1传的是ls,exec2直接用的arglist[0],不过由定义可得这两个等价,所以运行结果是相同的。

运行结果如下:

exec3

  • 此程序指定了环境变量,然后依然执行了ls -l指令,成功后没有返回,所以最后一句话不会输出,结果依然相同。
  • 相关代码
#include <stdio.h>
 #include <unistd.h>

int main()
{
    char    *arglist[3];
    char*myenv[3];
    myenv[0] = "PATH=:/bin:";
    myenv[1] = NULL;

    arglist[0] = "ls";
    arglist[1] = "-l";
    arglist[2] = 0 ;
    printf("* * * About to exec ls -l\n");

    execlp("ls", "ls", "-l", NULL);
    printf("* * * ls is done. bye\n");
}
  • 函数说明:execlp()会从PATH 环境变量所指的目录中查找符合参数file的文件名,找到后便执行该文件,然后将第二个以后的参数当做该文件的argv[0]、argv[1]……,最后一个参数必须用空指针(NULL)作结束。如果用常数0来表示一个空指针,则必须将它强制转换为一个字符指针,否则将它解释为整形参数,如果一个整形数的长度与char * 的长度不同,那么exec函数的实际参数就将出错。如果函数调用成功,进程自己的执行代码就会变成加载程序的代码,execlp()后边的代码也就不会执行了.
  • 返回值:如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno 中。也就是说,这个代码指定了环境变量,然后依然执行了ls -l指令,成功后没有返回,所以最后一句话不会输出。运行结果同exec1.

运行结果如下:

forkdemo1

  • 使用fork创建子进程的父进程,调用fork一次,打印两个输出行
  • 相关代码
#include "csapp.h"

int main() 
{
 pid_t pid;
 int x = 1;

 pid = Fork(); //line:ecf:forkreturn//父进程和子进程中x的值都为1
 if (pid == 0) {  /* Child */
printf("child : x=%d\n", ++x); //子进程增加并输出它的x的拷贝
exit(0);
}

/* Parent */
printf("parent: x=%d\n", --x); //父进程减少和输出它的x的拷贝
exit(0);
}

运行结果如下:

forkdemo3

  • 父进程返回调用进程子进程的PID,不为0,输出 i am the parent……
  • 相关代码
 #include    <stdio.h>
 #include    <stdlib.h>
 #include    <unistd.h>

int main()
{
    int fork_rv;

    printf("Before: my pid is %d\n", getpid());

    fork_rv = fork();     

    if ( fork_rv == -1 )     
        perror("fork");
    else if ( fork_rv == 0 ){ 
        printf("I am the child.  my pid=%d\n", getpid());

        exit(0);
    }
    else{
        printf("I am the parent. my child is %d\n", fork_rv);
        exit(0);
    }

    return 0;
}

运行结果如下:

forkdemo4

  • getpid返回调用进程的PID
  • getppid返回它的父进程的PID
  • 相关代码
 #include    <stdio.h>
 #include    <stdlib.h>
 #include    <unistd.h>

int main()
{
    int fork_rv;

    printf("Before: my pid is %d\n", getpid());

    fork_rv = fork(); //fork产生子进程

    if ( fork_rv == -1 ) 
        perror("fork");

    else if ( fork_rv == 0 ){ 
        printf("I am the child.  my pid=%d\n", getpid());
        printf("parent pid= %d, my pid=%d\n", getppid(), getpid());
        exit(0);
    }

    else{
        printf("I am the parent. my child is %d\n", fork_rv);
        sleep(10);
        exit(0);
    }

    return 0;
}

运行结果如下:

forkgdb

  • 父进程和子进程这两个线程是并发运行的独立进程,一个在休眠时另一个在执行,两个相互独立不干扰。
  • 相关代码
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>

int  gi=0;
int main()
{
    int li=0;
    static int si=0;
    int i=0;

    pid_t pid = fork();
    if(pid == -1){
        exit(-1);
    }
    else if(pid == 0){
        for(i=0; i<5; i++){
            printf("child li:%d\n", li++);
            sleep(1);
            printf("child gi:%d\n", gi++);
            printf("child si:%d\n", si++);
        }
        exit(0);

    }
    else{
        for(i=0; i<5; i++){
            printf("parent li:%d\n", li++);
            printf("parent gi:%d\n", gi++);
            sleep(1);
            printf("parent si:%d\n", si++);
        }
    exit(0);    

    }
    return 0;
}

运行结果如下:

psh1

  • 代码分析:这个代码就相当于你输入要执行的指令,回车表示输入结束,然后输入的每个参数对应到函数中,再调用对应的指令。

运行结果如下:

psh2

  • 比起psh1来,多了循环判断,不退出的话就会一直要你输入指令。

运行结果如下:

testbuf1:

  • 效果是先输出hello,然后换行。之后不退出。

运行结果如下:

testbuf2

  • 效果同上
  • 由此可知:fflush(stdout)的效果和换行符\n是一样的。

testbuf3

  • 代码分析:将内容格式化输出到标准错误、输出流中。

运行结果如下:

20145312 《信息安全系统设计基础》第12周学习总结

代码总结

testpid

  • 代码分析:输出当前进程pid和当前进程的父进程的pid。

运行结果如下:

testsystem

  • 代码分析:system()——执行shell命令,也就是向dos发送一条指令。这里是后面可以跟两个参数,然后向dos发送这两个命令,分别执行。如下图,输入ls和dir两个指令后,可以看到分别执行了。

运行结果如下:

waitdemo1

  • 代码分析:如果有子进程,则终止子进程,成功返回子进程pid。

运行结果如下:

waitdemo2

  • 代码分析:这个比起waitdemo1来就是多了一个子进程的状态区分,把状态拆分成三块,exit,sig和core。

运行结果如下:

posted @ 2016-12-03 20:06  20145312袁心  阅读(166)  评论(1编辑  收藏  举报