ftok与fork

   ftok函数编辑

系统建立IPC通讯 ( 消息队列信号量共享内存) 时必须指定一个ID值。通常情况下,该id值通过ftok函数得到。

2ftok原型编辑

头文件
#include < sys/types.h>
#include <sys/ipc.h>
函数原型:
key_t ftok( const char * fname, int id )
fname就是你指定的文件名(已经存在的文件名),一般使用 当前目录,如:
key_t key;
key = ftok(".", 1); 这样就是将fname设为 当前目录
id是子序号。虽然是int类型,但是只使用8bits,即(0-255)。
在一般的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 );[/code]
同一段程序,用于保证两个不同用户下的两组相同程序获得互不干扰的IPC键值。
由于etc/ config.ini(假定)为应用系统的关键配置文件,因此不存在被轻易 删除的问题——即使被删,也会很快被发现并重建(此时应用系统也将被重启)。
ftok()的设计目的也在于此。

分叉函数fork编辑

头文件

1
2
#include<unistd.h>/*#包含<unistd.h>*/
#include<sys/types.h>/*#包含<sys/types.h>*/

函数原型

pid_t forkvoid);
(pid_t 是一个 宏定义,其实质是int 被定义在# include< sys/types.h>中)
返回值: 若成功调用一次则返回两个值,子进程返回0, 父进程返回子进程ID;否则,出错返回-1

函数说明

一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而 父进程中返回子进程ID。
子进程是 父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述 存储空间的“副本”,这意味着父子进程间不共享这些存储空间。
UNIX将复制 父进程地址空间内容给子进程,因此,子进程有了独立的地址空间。在不同的UNIX (Like)系统下,我们无法确定fork之后是子进程先运行还是父进程先运行,这依赖于系统的实现。所以在移植代码的时候我们不应该对此作出任何的假设。
为什么fork会返回两次?
由于在复制时复制了 父进程堆栈段,所以两个进程都停留在fork函数中,等待返回。因此fork函数会返回两次,一次是在 父进程中返回,另一次是在子进程中返回,这两次的返回值是不一样的。过程如下图。
  1. fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
      在父进程中,fork返回新创建子进程的进程ID;
  2. 在子进程中,fork返回0;
  3. 如果出现错误,fork返回一个负值。
在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。
引用一位网友的话来解释fork函数返回的值为什么在父子进程中不同。“其实就相当于链表,进程形成了链表,父进程的fork函数返回的值指向子进程的进程id, 因为子进程没有子进程,所以其fork函数返回的值为0.
调用fork之后,数据、 堆栈有两份,代码仍然为一份但是这个 代码段成为两个进程的共享代码段都从fork函数中返回,箭头表示各自的执行处。当父子进程有一个想要修改数据或者堆栈时,两个进程真正分裂。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<sys/types.h>//对于此程序而言此头文件types.h用不到
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
 
intmain(intargc, char **argv) /*整数类型主函数*/
{
pid_tpid=fork(); /*传递参数*/
if (pid<0) /*如果(进程标记<0)*/
{
fprintf (stderr, "错误!" );
}
elseif(pid==0) /*否则如果(进程标记==0)*/
{
printf ( "这是子进程!" );
_exit(0);
}
else /*否则*/ {
printf ( "这是父进程!子进程的进程标记为=%d" ,pid);
}
//可能需要时候wait或waitpid函数等待子进程的结束并获取结束状态
exit (0);
}
注意!样例代码仅供参考,样例代码存在着父进程在子进程结束前结束的可能性。必要的时候可以使用wait或 waitpid函数让父进程等待子进程的结束并获取子进程的返回状态。
fork()在Linux系统中的返回值是没有NULL的.
Error Codes
出错返回 错误信息如下:
EAGAIN
达到进程数上限.
ENOMEM
没有足够空间给一个新进程分配.
fork函数的特点概括起来就是“调用一次,返回两次”,在 父进程中调用一次,在父进程和子进程中各返回一次。
fork的另一个特性是所有由 父进程打开的描述符都被复制到子进程中。父、子进程中相同编号的 文件描述符内核中指向同一个file 结构体,也就是说,file结构体的 引用计数要增加。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值