标签:i/o types 存在 gid 通道 共享内存 byte 因此 格式
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);
#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");
}
进程间通信(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是向共享内存发送命令的参数。
代码
```
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()函数
#include <stdio.h>
FILE *popen(const char *command, const char *open_mode);
int pclose(FILE *stream);
popen()函数首先调用一个shell,然后把command作为参数传递给shell。这样每次调用popen()函数都需要启动两个进程;但是由于在Linux中,所(parameter expansion)都是由shell执行的,这样command中包含的所有参数扩展都可以在command程序启动之前完成。pipe()函数
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *fifo_name, mode_t mode);
popen()函数只能返回一个管道描述符,并且返回的是文件流(file stream),可以使用函数fread()和fwrite()来访问。pipe()函数可以返回两个管道描述符:pipefd[0]和pipefd[1],任何写入pipefd[1]的数据都可pipefd[0]读回;pipe()函数返回的是文件描述符(file descriptor),因此只能使用底层的read()和write()系统调用来访问。pipe()函数通常用来实现父子进程之间的通信。20155212 2017-2018-1 《信息安全系统设计》第10周学习总结
标签:i/o types 存在 gid 通道 共享内存 byte 因此 格式
原文地址:http://www.cnblogs.com/dky20155212/p/7900371.html