20155212 2017-2018-1 《信息安全系统设计》第10周学习总结
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20155212 2017-2018-1 《信息安全系统设计》第10周学习总结相关的知识,希望对你有一定的参考价值。
20155212 2017-2018-1 《信息安全系统设计》第10周学习总结
stat命令的实现-mysate
- 要求:学习使用stat(1),并用C语言实现
- 学习
stat(1)
- 功能:显示文件或者文件系统信息
- 语法:
stat [选项] 文件
- 选项参数:
null
:显示详细信息-l
:链接-f
:不显示文件的信息,而显示其所在文件系统的信息-t
:显示简洁的信息-c
:以指定格式输出
man 1 stat
查看stat
命令- 使用
stat
命令
- 使用
man -k stat | grep 2
函数找到如下 - 使用
man 2 stat
查看 使用
stat()
函数会获得stat结构体struct stat { dev_t st_dev; /* ID of device containing file -文件所在设备的ID*/ ino_t st_ino; /* inode number -inode节点号*/ mode_t st_mode; /* 文件的类型和存取的权限*/ nlink_t st_nlink; /* number of hard links -链向此文件的连接数(硬连接)*/ uid_t st_uid; /* user ID of owner -user id*/ gid_t st_gid; /* group ID of owner - group id*/ dev_t st_rdev; /* device ID (if special file) -设备号,针对设备文件*/ off_t st_size; /* total size, in bytes -文件大小,字节为单位*/ blksize_t st_blksize; /* blocksize for filesystem I/O -系统块的大小*/ blkcnt_t st_blocks; /* number of blocks allocated -文件所占块数*/ time_t st_atime; /* time of last access -最近存取时间*/ time_t st_mtime; /* time of last modification -最近修改时间*/ time_t st_ctime; /* time of last status change - */ };
其中,比较特殊的是
st_mode
,st_mode是用特征位来表示文件类型的,特征位的定义如下:S_IFMT 0170000 文件类型的位遮罩 S_IFSOCK 0140000 socket S_IFLNK 0120000 符号链接(symbolic link) S_IFREG 0100000 一般文件 S_IFBLK 0060000 区块装置(block device) S_IFDIR 0040000 目录 S_IFCHR 0020000 字符装置(character device) S_IFIFO 0010000 先进先出(fifo) S_ISUID 0004000 文件的(set user-id on execution)位 S_ISGID 0002000 文件的(set group-id on execution)位 S_ISVTX 0001000 文件的sticky位 S_IRWXU 00700 文件所有者的遮罩值(即所有权限值) S_IRUSR 00400 文件所有者具可读取权限 S_IWUSR 00200 文件所有者具可写入权限 S_IXUSR 00100 文件所有者具可执行权限 S_IRWXG 00070 用户组的遮罩值(即所有权限值) S_IRGRP 00040 用户组具可读取权限 S_IWGRP 00020 用户组具可写入权限 S_IXGRP 00010 用户组具可执行权限 S_IRWXO 00007 其他用户的遮罩值(即所有权限值) S_IROTH 00004 其他用户具可读取权限 S_IWOTH 00002 其他用户具可写入权限 S_IXOTH 00001 其他用户具可执行权限
判断文件类型时,用对文件的st_mode的值与文件类型的位遮罩相与,再比较。
stat结构体中很多变量的类型都是不常用的,不能直接输出该类型,所以使用
grep -r *
查找同名变量的类型。以存储大小的变量st_size
为例,发现很多使用的long long
类型伪代码
input path;
struct state;
stat(path,state);
print(state);
- 产品代码 mystate.c,提交码云链接
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
void main(int argc, char *argv[])
{
struct stat state;
stat(argv[1], &state);
printf(" 文件:‘%s‘\\n", argv[1]);
printf(" 大小:%lld\\t", (long long)state.st_size);
printf("块:%lld\\t", (long long)state.st_blocks);
printf("IO块:%ld\\t", (long)state.st_blksize);
switch(state.st_mode & S_IFMT)
{
case S_IFBLK:
printf("块设备文件");
break;
case S_IFCHR:
printf("字符设备文件");
break;
case S_IFDIR:
printf("目录");
break;
case S_IFIFO:
printf("管道文件");
break;
case S_IFLNK:
printf("符号链接文件");
break;
case S_IFREG:
printf("普通文件");
break;
case S_IFSOCK:
printf("套接字文件");
break;
default:
break;
}
printf("\\n");
printf("设备:%xh/%ldd\\t", (long)state.st_dev, (long)state.st_dev);
printf("Inode:%ld\\t", (long)state.st_ino);
printf("硬链接:%ld\\n", (long)state.st_nlink);
printf("权限:(%o)\\t", (unsigned int)(state.st_mode & ~S_IFMT));
printf("Uid:(%ld)\\t", (long)state.st_uid);
printf("Gid:(%ld)\\n", (long)state.st_gid);
printf("最近访问:%s", ctime(&state.st_atim));
printf("最近更改:%s", ctime(&state.st_ctim));
printf("最近改动:%s", ctime(&state.st_mtim));
printf("创建时间:-");
printf("\\n");
}
- 测试代码,mystat 与stat(1)对比,提交截图
Linux下IPC机制
进程间通信(IPC,Inter-Process Communication)指至少两个进程或线程间传送数据或信号的一些技术或方法。
共享内存
共享内存允许两个或多个进程共享一定的存储区,因为不需要拷贝数据,所以这是最快的一种IPC。
原理:
共享内存是在多个进程之间共享内存区域的一种进程间的通信方式,由IPC为进程创建的一个特殊地址范围,它将出现在该进程的地址空间中。其他进程可以将同一段共享内存连接到自己的地址空间中。所有进程都可以访问共享内存中的地址,就好像它们是malloc分配的一样。如果一个进程向共享内存中写入了数据,所做的改动将立刻被其他进程看到。内存头文件
#include <sys/types.h> #include <sys/stat.h> #include <sys/shm.h>
结构shmid_ds结构体(类似msgid_ds结构体)
strcut shmid_ds{ struct ipc_perm shm_perm; size_t shm_segsz; time_t shm_atime; time_t shm_dtime; ...... }
- 共享内存函数定义
int shmget(key_t key,size_t size,int shmflg); //shmget函数用来创建一个新的共享内存段, 或者访问一个现有的共享内存段(不同进程只要key值相同即可访问同一共享内存段)。第一个参数key是ftok生成的键值,第二个参数size为共享内存的大小,第三个参数sem_flags是打开共享内存的方式 eg.int shmid = shmget(key, 1024, IPC_CREATE | IPC_EXCL | 0666);//第三个参数参考消息队列int msgget(key_t key,int msgflag); void *shmat(int shm_id,const void *shm_addr,int shmflg); //shmat函数通过shm_id将共享内存连接到进程的地址空间中。第二个参数可以由用户指定共享内存映射到进程空间的地址,shm_addr如果为0,则由内核试着查找一个未映射的区域。返回值为共享内存映射的地址 eg.char *shms = (char *)shmat(shmid, 0, 0);//shmid由shmget获得 int shmdt(const void *shm_addr) //shmdt函数将共享内存从当前进程中分离。 参数为共享内存映射的地址。 eg.shmdt(shms) int shmctl(int shm_id,int cmd,struct shmid_ds *buf);//shmctl函数是控制函数,使用方法和消息队列msgctl()函数调用完全类似。参数一shm_id是共享内存的句柄,cmd是向共享内存发送的命令,最后一个参数buf是向共享内存发送命令的参数。
- 特点
- 共享内存允许两个或多个进程共享一定的存储区,因为不需要拷贝数据,所以这是最快的一种IPC
- 共享内存本身并没有同步机制,需要程序员使用诸如信号量等手段进行同步控制,增加了其复杂性
- 示例
- 写进程
代码
```include
include
include <sys/shm.h>
include
include
include <sys/types.h>
include <sys/ipc.h>
include
define BUF_SIZE 4096
int main()
{
void *shm_addr = NULL;
char buffer[BUF_SIZE];int shmid; // 使用约定的键值创建共享内存 shmid = shmget((key_t) 1234, BUF_SIZE, 0666 | IPC_CREAT); printf("shmid : %u\\n", shmid); if (shmid < 0) { perror("shmget error!"); exit(1); } // 将共享内存附加到本进程 shm_addr = shmat(shmid, NULL, 0); if (shm_addr == (void *) -1) { perror("shmat error!"); exit(1); } // 写入数据 bzero(buffer, BUF_SIZE); sprintf(buffer, "Hello, My PID is %u\\n", (unsigned int) getpid()); printf("send data: %s\\n", buffer); memcpy(shm_addr, buffer, strlen(buffer)); sleep(5); // 分离 if (shmdt(shm_addr) == -1) { printf("shmdt error!\\n"); exit(1); }
}
``- 运行结果![](https://images2018.cnblogs.com/blog/1043723/201711/1043723-20171126165304640-412383960.png) -
ipcs -m`命令查看系统中的确存在标识符为15466507的共享内存区域。写进程已经跟共享内存分离,所以状态连接数为0 - 读进程
- 代码
#include <stdio.h> #include <stdlib.h> #include <sys/shm.h> #include <sys/ipc.h> #include <sys/types.h> #include <unistd.h> #include <string.h> #include <errno.h> #define BUF_SIZE 4096 int main() { void *shm_addr = NULL; int shmid; // 使用约定的键值打开共享内存 shmid = shmget((key_t) 1234, BUF_SIZE, IPC_CREAT); printf("shmid : %u\\n", shmid); if (shmid == -1) { perror("shmget error!"); exit(1); } // 将共享内存附加到本进程 shm_addr = shmat(shmid, NULL, 0); if (shm_addr == (void *) -1) { perror("shmat error!"); exit(1); } // 读取数据 char tmp[BUF_SIZE]; bzero(tmp, BUF_SIZE); memcpy(tmp, shm_addr, BUF_SIZE); printf("read from shared memory: %s\\n", tmp); sleep(5); // 分离 if (shmdt(shm_addr) == -1) { printf("shmdt error!\\n"); exit(1); } // 删除共享内存 if (shmctl(shmid, IPC_RMID, 0) == -1) { printf("shmctl error!\\n"); exit(1); } }
- 运行结果
ipcs -m
查看,没有15466507的进程,因为读进程执行完毕后删除了共享内存区域
- 写进程
管道
在Linux系统中,我们经常通过符号“|”来使用管道,用以连接两个或多个命令。实际上,管道是进程与进程间的数据流通道,它使得数据可以以一种“流”的形式在进程间流动。管道也是Unix/Linux系统中一种最常见的进程间通信方式,它在两个通信进程之间实现一个数据流的通道从而进行信息传递。
- 原理
在两个程序之间传递数据的最简单的方法是使用popen()和pclose()函数
popen()函数首先调用一个shell,然后把command作为参数传递给shell。这样每次调用popen()函数都需要启动两个进程;但是由于在Linux中,所(parameter expansion)都是由shell执行的,这样command中包含的所有参数扩展都可以在command程序启动之前完成。#include <stdio.h> FILE *popen(const char *command, const char *open_mode); int pclose(FILE *stream);
pipe()函数
popen()函数只能返回一个管道描述符,并且返回的是文件流(file stream),可以使用函数fread()和fwrite()来访问。pipe()函数可以返回两个管道描述符:pipefd[0]和pipefd[1],任何写入pipefd[1]的数据都可pipefd[0]读回;pipe()函数返回的是文件描述符(file descriptor),因此只能使用底层的read()和write()系统调用来访问。pipe()函数通常用来实现父子进程之间的通信。#include <sys/types.h> #include <sys/stat.h> int mkfifo(const char *fifo_name, mode_t mode);
- 特点
- 只支持单向数据流
- 只能用于具有亲缘关系的进程之间;
- 没有名字
- 管道的缓冲区是有限的(管道制存在于内存中,在管道创建时,为缓冲区分配一个页面大小)
- 管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息(或命令、或记录)等等
- 示例: 构造父子进程间任意方向的的数据通道
- 代码
- 运行结果
FIFO
- 原理
- 特点
- 示例
信号
- 原理
- 特点
- 示例
消息队列
- 原理
- 特点
- 示例
参考
以上是关于20155212 2017-2018-1 《信息安全系统设计》第10周学习总结的主要内容,如果未能解决你的问题,请参考以下文章
20155212 2017-2018-1 《信息安全系统设计》第9周学习总结
2017-2018-1 20155212 《信息安全系统设计基础》第14周学习总结
2017-2018-1 20155208 20155212 实验三 实时系统