System V IPC分为三种:
- System V消息队列
- System V信号量
- System V共享内存区
这三种类型的IPC使用key_t值做为它们的名字。key_t这个数据类型在<sys/types.h>有定义,通常是一个至少32位的整数。
我们通常使用ftok()函数(可以如此记忆:file to key)把一个已存在的路径名和一个整数标识符转换成一个key_t值,称为IPC键。(当然,我们也可以不用ftok函数来生成该键,指定一个整数也是可以的,当然你需要考虑键的正负问题)。
看下ftok的声明:
1
2
3
|
#include <sys/ipc.h>
/* Generates key for System V style IPC. */
key_t ftok (
const
char
*pathname,
int
proj_id);
|
pathname 通常是跟本应用用关的目录;proj_id指的是本应用所用到的IPC的一个序列号;成功返回IPC键,失败返回-1;
注:两进程如在pathname和proj_id上达成一致(或约定好),双方就都能够通过调用ftok函数得到同一个IPC键。
那么ftok是怎么实现的呢?《UNIX网络编程》上讲到,ftok的实现是组合了三个值:
- pathname所在文件系统的信息(stat结构的st_dev成员)
- pathname在本文件系统内的索引节点号(stat结构的st_ino成员)
- id的低序8位(不能为0)
具体如何组合的,根据系统实现而不同。
使用ftok()需要注意的问题:
- pathname指定的目录(文件)必须真实存在且调用进程可访问,否则ftok返回-1;
- pathname指定的目录(文件)不能在程序运行期间删除或创建。因为文件每次创建时由系统赋予的索引节点可能不一样。这样一来,通过同一个pathname与proj_id就不能保证生成同一个IPC键。
附:文件属性结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
struct
stat
{
dev_t st_dev;
/* device */
ino_t st_ino;
/* inode */
mode_t st_mode;
/* protection */
nlink_t st_nlink;
/* number of hard links */
uid_t st_uid;
/* user ID of owner */
gid_t st_gid;
/* group ID of owner */
dev_t st_rdev;
/* device type (if inode device) */
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 */
};
|
获取文件属性的函数有如下几个:
1
2
3
|
int
stat(
const
char
*file_name,
struct
stat *buf);
int
fstat(
int
filedes,
struct
stat *buf);
int
lstat(
const
char
*file_name,
struct
stat *buf);
|
下面通过例子来看一下如何获取:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int
main()
{
const
char
fname[] =
"main.c"
;
struct
stat stat_info;
if
(0 != stat(fname, &stat_info))
{
perror
(
"取得文件信息失败!"
);
exit
(1);
}
printf
(
"文件所在设备编号:%ld\r\n"
, stat_info.st_dev);
printf
(
"文件所在文件系统索引:%ld\r\n"
, stat_info.st_ino);
printf
(
"文件的类型和存取的权限:%d\r\n"
, stat_info.st_mode);
printf
(
"连到该文件的硬连接数目:%d\r\n"
, stat_info.st_nlink);
printf
(
"文件所有者的用户识别码:%d\r\n"
, stat_info.st_uid);
printf
(
"文件所有者的组识别码:%d\r\n"
, stat_info.st_gid);
printf
(
"装置设备文件:%ld\r\n"
, stat_info.st_rdev);
printf
(
"文件大小:%ld\r\n"
, stat_info.st_size);
printf
(
"文件系统的I/O缓冲区大小:%ld\r\n"
, stat_info.st_blksize);
printf
(
"占用文件区块的个数(每一区块大小为512个字节):%ld\r\n"
, stat_info.st_blocks);
printf
(
"文件最近一次被存取或被执行的时间:%ld\r\n"
, stat_info.st_atime);
printf
(
"文件最后一次被修改的时间:%ld\r\n"
, stat_info.st_mtime);
printf
(
"最近一次被更改的时间:%ld\r\n"
, stat_info.st_ctime);
return
0;
}
|
编译并执行输出:
$ gcc -o getstat main.c
$ ./getstat
文件所在设备编号:2051
文件所在文件系统索引:61079722
文件的类型和存取的权限:33188
连到该文件的硬连接数目:1
文件所有者的用户识别码:502
文件所有者的组识别码:503
装置设备文件:0
文件大小:1210
文件系统的I/O缓冲区大小:4096
占用文件区块的个数(每一区块大小为512个字节):8
文件最近一次被存取或被执行的时间:1320997735
文件最后一次被修改的时间:1320994242
最近一次被更改的时间:1320994242
出处:http://my.oschina.net/renhc/blog/34991