深入解读键值产生原理,linux中的软链接和硬链接
2014-04-14 10:10
183 查看
键值 = 文件标示符 + 项目ID
当用到进程间的通信时,必须要注意到的是键值是怎么产生的,我们知道任何一个文件时通过文件名来访问的,而内核在对应的给其一个值,也就是文件标示符。
系统建立IPC通讯(如消息队列、共享内存时)必须指定一个ID值 。通常情况下,该id值通过ftok函数得到 。 ftok原型如下:
key_t ftok( char * fname, int id )
此时这个 id也就是项目 ID,最后将两者结合生成了键值!这里所谓的文件标示符其实下面提到的 内核的物理编号,也就是索引节点 inode。
参数说明: fname就时您指定的文档名, id是子序号。
关于linux中的软链接和硬链接
Linux中有两种类型的链接:(这个与 Windows上 FAT32 或 NTFS是不一样的!)
硬链接是利用Linux中为每个文件分配的物理编号——inode建立链接。因此,硬链接不能跨越文件系统。(用ls –i命令可以查看目录下文件的inode编程)。
软链接(符号链接)是利用文件的路径名建立链接。通常建立软链接使用绝对路径而不是相对路径,以最大限度增加可移植性。
i节点包含了所有与文件有关的信息:文件类型、文件存取许可权位、文件长度和指向该文件所占用的数据块的指针等,stat结构中的大多数信息都取自 i节点。只有两数据项存放在目录项中:文件名和i节点编号数。
因为目录项中的i节点编号数指向同一文件系统中的 i节点,所以不能使一个目录项指向另一个文件系统的i节点。硬链接不能跨文件系统,软链接可以。即每个文件系统有自己的i节点编号。
在一般的UNIX实现中,是将文档的索引节点号取出,前面加上子序号得到key_t的返回值。 如指定文档的索引节点号为65538,换算成16进制为0x010002,而您指定的ID值为38,换算成16进制 为 0x26,则最后的key_t返回值为0x26010002。
查询文档索引节点号的方法是: ls -i
当删除重建文档后,索引节点号由操作系统根据当时文档系统的使用情况分配,因此和原来不同,所以得到的索引节点号也不同。
假如要确保key_t值不变,要目确保ftok的文档不被删除 ,要么不用ftok,指定一个固定的key_t值。
另外说一句:在aix等操作系统上,有多个文档系统,会出现分布在不同的文档系统上的两个文档具备相同的索引节点号,此时用ftok对这两个文档进行操作,只要id参数不变,得到的key_t值相同,造成创建消息队列失败。但是这种情况相当少见罢了。
因为在开发中涉及多种系统平台,在系统移植时发现ftok()函数在不同平台下存在一定的差异性。当然,根本原因不在于ftok()本身,而应该是操作系统对于文件系统管理的差异性。
测试代码如下:
测试涉及的操作系统:RedHat AS3U3、Sco OpenServer 5.0.6、UnixWare 7.1.1、Solaris 9 x86 u7。
在RH AS3环境下,对aaa.txt进行修改后程序的输出值都有变化,说明该文件在修改后存储位置发生了变化。
在Sco OpenServer 5.0.6、UnixWare 7.1.1、Solaris 9 x86 u7下执行相同的程序,无论对aaa.txt的文件内容做何种修改都对程序的输出无影响。
因此,如果在linux下通过ftok()产生ipc键值、且ftok()与配置文件相关,则在更改了配置文件后必须将应用重起。否则将导致不可预料的后果!
看以下程序:
头文件:
#include
#include
如下:
key_t ftok( char * fname, int id )
fname就是你指定的文件名(已经存在的文件名),一般使用当前目录,如:
key = ftok(".", 1); 这样就是将fname设为当前目录。
id是子序号。
在一般的UNIX实现中,是将文件的索引节点号取出,前面加上子序号得到key_t的返回值。
如指定文件的索引节点号为65538,换算成16进制为0x010002,而你指定的ID值为38,换算成16进制为0x26,则最后的key_t返回值为0x26010002。
查询文件索引节点号的方法是: ls -i
当删除重建文件后,索引节点号由操作系统根据当时文件系统的使用情况分配,因此与原来不同,所以得到的索引节点号也不同。
如果要确保key_t值不变,要么确保ftok的文件不被删除,要么不用ftok,指定一个固定的key_t值,比如:
#define IPCKEY 0x111
char path[256];
sprintf( path, "%s/etc/config.ini", (char*)getenv("HOME") );
msgid=ftok( path, IPCKEY );
同一段程序,用于保证两个不同用户下的两组相同程序获得互不干扰的IPC键值。
由于etc/config.ini(假定)为应用系统的关键配置文件,因此不存在被轻易删除的问题——即使被删,也会很快被发现并重建(此时应用系统也将被重起)。
一个ftok用于共享内存的实例:
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9
10 #define SIZE 1024
11
12 extern int errno;
13
14 int main()
15 {
16 int shmid;
17 char *shmptr;
18 key_t key;
19 pid_t pid;
20
21 if((pid = fork()) < 0)
22 {
23 printf("fork error:%s\n", strerror(errno));
24 return -1;
25 }
26 else if(pid == 0)
27 {
28 sleep(2);
29 if((key = ftok("/dev/null", 1)) < 0)
30 {
31 printf("ftok error:%s\n", strerror(errno));
32 return -1;
33 }
34 if((shmid = shmget(key, SIZE, 0600)) < 0)
35 {
36 printf("shmget error:%s\n", strerror(errno));
37 exit(-1);
38 }
39
40 if((shmptr = (char*)shmat(shmid, 0, 0)) == (void*)-1)
41 {
42 printf("shmat error:%s\n", strerror(errno));
43 exit(-1);
44 }
45 //memcpy(shmptr, "hello world", sizeof("hello world"));
46 printf("child:pid is %d,share memory from %lx to %lx, content:%s\n",getpid(), (unsigned long)shmptr, (unsigned long)(shmptr + SIZE
47 ), shmptr);
48 printf("child process sleep 2 seconds\n");
49 sleep(2);
50 if((shmctl(shmid, IPC_RMID, 0) < 0))
51 {
52 printf("shmctl error:%s\n", strerror(errno));
53 exit(-1);
54 }
55 exit(0);
56 }
57 //parent
58 else
59 {
60 if((key = ftok("/dev/null", 1)) < 0)
61 {
62 printf("ftok error:%s\n", strerror(errno));
63 return -1;
64 }
65 if((shmid = shmget(key, SIZE, 0600|IPC_CREAT|IPC_EXCL)) < 0)
66
67 {
68 printf("shmget error:%s\n", strerror(errno));
69 exit(-1);
70 }
71
72 if((shmptr = (char*)shmat(shmid, 0, 0)) == (void*)-1)
73 {
74 printf("shmat error:%s\n", strerror(errno));
75 exit(-1);
76 }
77 memcpy(shmptr, "hello world", sizeof("hello world"));
78 printf("parent:pid is %d,share memory from %lx to %lx, content:%s\n",getpid(),(unsigned long)shmptr, (unsigned long)(shmptr + SIZE
79 ), shmptr);
80 printf("parent process sleep 2 seconds\n");
81 sleep(2);
82 if((shmctl(shmid, IPC_RMID, 0) < 0))
83 {
84 printf("shmctl error:%s\n", strerror(errno));
85 exit(-1);
86 }
87 }
88
89 waitpid(pid,NULL,0);
90 exit(0);
91 }
当用到进程间的通信时,必须要注意到的是键值是怎么产生的,我们知道任何一个文件时通过文件名来访问的,而内核在对应的给其一个值,也就是文件标示符。
系统建立IPC通讯(如消息队列、共享内存时)必须指定一个ID值 。通常情况下,该id值通过ftok函数得到 。 ftok原型如下:
key_t ftok( char * fname, int id )
此时这个 id也就是项目 ID,最后将两者结合生成了键值!这里所谓的文件标示符其实下面提到的 内核的物理编号,也就是索引节点 inode。
参数说明: fname就时您指定的文档名, id是子序号。
关于linux中的软链接和硬链接
Linux中有两种类型的链接:(这个与 Windows上 FAT32 或 NTFS是不一样的!)
硬链接是利用Linux中为每个文件分配的物理编号——inode建立链接。因此,硬链接不能跨越文件系统。(用ls –i命令可以查看目录下文件的inode编程)。
软链接(符号链接)是利用文件的路径名建立链接。通常建立软链接使用绝对路径而不是相对路径,以最大限度增加可移植性。
i节点包含了所有与文件有关的信息:文件类型、文件存取许可权位、文件长度和指向该文件所占用的数据块的指针等,stat结构中的大多数信息都取自 i节点。只有两数据项存放在目录项中:文件名和i节点编号数。
因为目录项中的i节点编号数指向同一文件系统中的 i节点,所以不能使一个目录项指向另一个文件系统的i节点。硬链接不能跨文件系统,软链接可以。即每个文件系统有自己的i节点编号。
在一般的UNIX实现中,是将文档的索引节点号取出,前面加上子序号得到key_t的返回值。 如指定文档的索引节点号为65538,换算成16进制为0x010002,而您指定的ID值为38,换算成16进制 为 0x26,则最后的key_t返回值为0x26010002。
查询文档索引节点号的方法是: ls -i
当删除重建文档后,索引节点号由操作系统根据当时文档系统的使用情况分配,因此和原来不同,所以得到的索引节点号也不同。
假如要确保key_t值不变,要目确保ftok的文档不被删除 ,要么不用ftok,指定一个固定的key_t值。
另外说一句:在aix等操作系统上,有多个文档系统,会出现分布在不同的文档系统上的两个文档具备相同的索引节点号,此时用ftok对这两个文档进行操作,只要id参数不变,得到的key_t值相同,造成创建消息队列失败。但是这种情况相当少见罢了。
因为在开发中涉及多种系统平台,在系统移植时发现ftok()函数在不同平台下存在一定的差异性。当然,根本原因不在于ftok()本身,而应该是操作系统对于文件系统管理的差异性。
测试代码如下:
#include ; #include ; main() { sprintf( "key=%0x/n", ftok( "aaa.txt", 1000 ) ); }
测试涉及的操作系统:RedHat AS3U3、Sco OpenServer 5.0.6、UnixWare 7.1.1、Solaris 9 x86 u7。
在RH AS3环境下,对aaa.txt进行修改后程序的输出值都有变化,说明该文件在修改后存储位置发生了变化。
在Sco OpenServer 5.0.6、UnixWare 7.1.1、Solaris 9 x86 u7下执行相同的程序,无论对aaa.txt的文件内容做何种修改都对程序的输出无影响。
因此,如果在linux下通过ftok()产生ipc键值、且ftok()与配置文件相关,则在更改了配置文件后必须将应用重起。否则将导致不可预料的后果!
看以下程序:
头文件:
#include
#include
如下:
key_t ftok( char * fname, int id )
fname就是你指定的文件名(已经存在的文件名),一般使用当前目录,如:
key = ftok(".", 1); 这样就是将fname设为当前目录。
id是子序号。
在一般的UNIX实现中,是将文件的索引节点号取出,前面加上子序号得到key_t的返回值。
如指定文件的索引节点号为65538,换算成16进制为0x010002,而你指定的ID值为38,换算成16进制为0x26,则最后的key_t返回值为0x26010002。
查询文件索引节点号的方法是: ls -i
当删除重建文件后,索引节点号由操作系统根据当时文件系统的使用情况分配,因此与原来不同,所以得到的索引节点号也不同。
如果要确保key_t值不变,要么确保ftok的文件不被删除,要么不用ftok,指定一个固定的key_t值,比如:
#define IPCKEY 0x111
char path[256];
sprintf( path, "%s/etc/config.ini", (char*)getenv("HOME") );
msgid=ftok( path, IPCKEY );
同一段程序,用于保证两个不同用户下的两组相同程序获得互不干扰的IPC键值。
由于etc/config.ini(假定)为应用系统的关键配置文件,因此不存在被轻易删除的问题——即使被删,也会很快被发现并重建(此时应用系统也将被重起)。
一个ftok用于共享内存的实例:
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9
10 #define SIZE 1024
11
12 extern int errno;
13
14 int main()
15 {
16 int shmid;
17 char *shmptr;
18 key_t key;
19 pid_t pid;
20
21 if((pid = fork()) < 0)
22 {
23 printf("fork error:%s\n", strerror(errno));
24 return -1;
25 }
26 else if(pid == 0)
27 {
28 sleep(2);
29 if((key = ftok("/dev/null", 1)) < 0)
30 {
31 printf("ftok error:%s\n", strerror(errno));
32 return -1;
33 }
34 if((shmid = shmget(key, SIZE, 0600)) < 0)
35 {
36 printf("shmget error:%s\n", strerror(errno));
37 exit(-1);
38 }
39
40 if((shmptr = (char*)shmat(shmid, 0, 0)) == (void*)-1)
41 {
42 printf("shmat error:%s\n", strerror(errno));
43 exit(-1);
44 }
45 //memcpy(shmptr, "hello world", sizeof("hello world"));
46 printf("child:pid is %d,share memory from %lx to %lx, content:%s\n",getpid(), (unsigned long)shmptr, (unsigned long)(shmptr + SIZE
47 ), shmptr);
48 printf("child process sleep 2 seconds\n");
49 sleep(2);
50 if((shmctl(shmid, IPC_RMID, 0) < 0))
51 {
52 printf("shmctl error:%s\n", strerror(errno));
53 exit(-1);
54 }
55 exit(0);
56 }
57 //parent
58 else
59 {
60 if((key = ftok("/dev/null", 1)) < 0)
61 {
62 printf("ftok error:%s\n", strerror(errno));
63 return -1;
64 }
65 if((shmid = shmget(key, SIZE, 0600|IPC_CREAT|IPC_EXCL)) < 0)
66
67 {
68 printf("shmget error:%s\n", strerror(errno));
69 exit(-1);
70 }
71
72 if((shmptr = (char*)shmat(shmid, 0, 0)) == (void*)-1)
73 {
74 printf("shmat error:%s\n", strerror(errno));
75 exit(-1);
76 }
77 memcpy(shmptr, "hello world", sizeof("hello world"));
78 printf("parent:pid is %d,share memory from %lx to %lx, content:%s\n",getpid(),(unsigned long)shmptr, (unsigned long)(shmptr + SIZE
79 ), shmptr);
80 printf("parent process sleep 2 seconds\n");
81 sleep(2);
82 if((shmctl(shmid, IPC_RMID, 0) < 0))
83 {
84 printf("shmctl error:%s\n", strerror(errno));
85 exit(-1);
86 }
87 }
88
89 waitpid(pid,NULL,0);
90 exit(0);
91 }
相关文章推荐
- 深入解读键值产生原理,linux中的软链接和硬链接(转)
- 分享:深入理解Linux的软链接和硬链接
- Linux深入理解硬链接与软链接
- 深入理解Linux的软链接和硬链接等Linux易漏知识
- Linux下的软链接和硬链接的不同(转载)
- Linux下软链接与硬链接
- linux 链接ln的使用 创建和删除符号连接(软、硬链接)
- LINUX 硬链接与软链接的区别,emacs对硬链接的影响
- 深入解读Quartz的原理
- 深入解读PHP插件机制原理
- linux 链接ln的使用 创建和删除符号连接(软、硬链接)
- linux 软件链接和硬链接
- 文件系统:文件句柄 inode vnode (多进程 dup 硬链接 软链接原理)
- Oracle数据块实现原理深入解读
- Oracle数据块实现原理深入解读
- 关于linux中的软链接和硬链接
- 深入解读Quartz的原理
- 转:深入解读Linux与Android的相互关系
- 深入研究Windows内部原理系列_全部链接
- 深入解读Quartz的原理