2017-2018-1 20155331 《信息安全系统设计基础》第十周课上作业

时间:2021-01-27 18:53:41

2017-2018-1 20155331 《信息安全系统设计基础》第十周课上作业

stat命令的实现-mysate

学习使用stat(1),并用C语言实现

  1. 提交学习stat(1)的截图

  2. man -k grep -r的使用
    2017-2018-1 20155331 《信息安全系统设计基础》第十周课上作业

通过学习理解到,stat命令主要用于显示文件或文件系统的详细信息,

-L:显示符号链接所指向文件的信息

-f:显示文件所在文件系统的信息

-t:以简洁方式输出信息

-c:以特定格式输出文件的某些信息

2017-2018-1 20155331 《信息安全系统设计基础》第十周课上作业

课下测试IPC

实验要求:研究Linux下IPC机制:原理,优缺点,每种机制至少给一个示例,提交研究博客的链接

共享内存

管道

FIFO

信号

消息队列

System V IPC

System V IPC指的是AT&T在System V.2发行版中引入的三种进程间通信工具:(1)信号量,用来管理对共享资源的访问 (2)共享内存,用来高效地实现进程间的数据共享 (3)消息队列,用来实现进程间数据的传递。我们把这三种工具统称为System V IPC的对象,每个对象都具有一个唯一的IPC标识符(identifier)。要保证不同的进程能够获取同一个IPC对象,必须提供一个IPC关键字(IPC key),内核负责把IPC关键字转换成IPC标识符。   

System V IPC具有相似的语法,一般操作如下:

(1)选择IPC关键字,可以使用如下三种方式:

   a)IPC_PRIVATE。由内核负责选择一个关键字然后生成一个IPC对象并把IPC标识符直接传递给另一个进程。
   b)直接选择一个关键字。
   c)使用ftok()函数生成一个关键字。

(2)使用semget()/shmget()/msgget()函数根据IPC关键字key和一个标志flag创建或访问IPC对象。如果key是IPC_PRIVATE;或者key尚未与已经存在的IPC对象相关联且flag中包含IPC_CREAT标志,那么就会创建一个全新的IPC对象。

(3)使用semctl()/shmctl()/msgctl()函数修改IPC对象的属性。

(4)使用semctl()/shmctl()/msgctl()函数和IPC_RMID标志销毁IPC实例。

System V IPC为每个IPC对象设置了一个ipc_perm结构体并在创建IPC对象的时候进行初始化。这个结构体中定义了IPC对象的访问权限和所有者:

struct ipc_perm{
   uid_t uid;   //所有者的用户id
   gid_t gid;   //所有者的组id
   uid_t cuid;  //创建者的用户id
   gid_t cgid;  //创建者的组id
   mode_t mode; //访问模式
   …
};

shell中管理IPC对象的命令是ipcs、ipcmk和ipcrm。

1、信号量(Semaphores)

System V的信号量集表示的是一个或多个信号量的集合。内核为每个信号量集维护一个semid_ds数据结构,而信号量集中的每个信号量使用一个无名结构体表示,这个结构体至少包含以下成员:
struct{
    unsigned short semval;//信号量值,总是>=0
    pid_t sempid;  //上一次操作的pid
   …
};

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
(1)创建或访问信号量
    * int semget(key_t key,int nsems,int flag); 
nsems指定信号量集中信号量的个数,如果只是获取信号量集的标识符(而非新建),那么nsems可以为0。flag的低9位作为信号量的访问权限位,类似于文件的访问权限;如果flag中同时指定了IPC_CREAT和IPC_EXCL,那么如果key已与现存IPC对象想关联的话,函数将会返回EEXIST错误。例如,flag可以为IPC_CREAT|0666。

(2)控制信号量集
    * int semctl(int semid,int semnum,int cmd,union semun arg);
对semid信号量集合执行cmd操作;cmd常用的两个值是:SETVAL初始化第semnum个信号量的值为arg.val;IPC_RMID删除信号量。

(3)对一个或多个信号量进行操作
    * int semop(int semid,struct sembuf *sops,unsigned nsops);
    * struct sembuf{
          unsigned short sem_num;  //信号量索引
          short   sem_op;     //对信号量进行的操作,常用的两个值为-1和+1,分别代表P、V操作
          short   sem_flag;   //比较重要的值是SEM_UNDO:当进程结束时,相应的操作将被取消;同时,如果进程结束时没有释放资源的话,系统会自动释放
       };

2、共享内存

共享内存允许两个或多个进程共享一定的存储区,因为不需要拷贝数据,所以这是最快的一种IPC。

#include <sys/ipc.h>
#include <sys/shm.h>
(1)创建或访问共享内存
    * int shmget(key_t key,size_t size,int shmflg);

(2)附加共享内存到进程的地址空间
    * void *shmat(int shmid,const void *shmaddr,int shmflg);//shmaddr通常为NULL,由系统选择共享内存附加的地址;shmflg可以为SHM_RDONLY

(3)从进程的地址空间分离共享内存
    * int shmdt(const void *shmaddr); //shmaddr是shmat()函数的返回值

(4)控制共享内存
    * int shmctl(int shmid,int cmd,struct shmid_ds *buf);
    * struct shmid_ds{
          struct ipc_perm shm_perm;
          …
      }; 
cmd的常用取值有:(a)IPC_STAT获取当前共享内存的shmid_ds结构并保存在buf中(2)IPC_SET使用buf中的值设置当前共享内存的shmid_ds结构(3)IPC_RMID删除当前共享内存

3.FIFO

FIFO原理:管道(FIFO)是一种特殊类型的文件,它在系统中以文件形式存在。这样克服了管道的弊端,他可以允许没有亲缘关系的进程间通信。
FIFO优缺点:方便一个进程向文件中写数据,方便一个进程将读出数据并丢弃向命名管道文件中写数据
实现代码:向命名管道文件中写数据
实现代码:从命名管道文件中读数据并丢弃

4、消息队列

消息队列保存在内核中,是一个由消息组成的链表。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
(1)创建或访问消息队列
* int msgget(key_t key,int msgflg);

(2)操作消息队列
    * int msgsnd(int msqid,const void *msg,size_t nbytes,int msgflg);
msg指向的结构体必须以一个long int成员开头,作为msgrcv()的消息类型,必须大于0。nbytes指的是msg指向结构体的大小,但不包括long int部分的大小
    * ssize_t msgrcv(int msqid,void *msg,size_t nbytes,long msgtype,int msgflg);
如果msgtype是0,就返回消息队列中的第一个消息;如果是正整数,就返回队列中的第一个该类型的消息;如果是负数,就返回队列中具有最小值的第一个消息,并且该最小值要小于等于msgtype的绝对值。

(3)控制消息队列
    * int msgctl(int msqid,int cmd,struct msqid_ds *buf);
    * struct msqid_ds{
          struct ipc_perm msg_perm;
          …
       };

5.管道

管道原理:管道实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另一进程就可以从管道的另一端将其读取出来。
管道优缺点:管道是由内核管理的一个缓冲区,一个缓冲区不需要很大,它被设计成为环形的数据结构,以便管道可以被循环利用。当管道中没有信息的话,从管道中读取的进程会等待,直到另一端的进程放入信息。
实现代码:向管道文件中写数据
实现代码:从管道文件中读数据