Unix学习(十)

来源:互联网 发布:javascript模式 下载 编辑:程序博客网 时间:2024/06/06 17:19

匿名本地网络
socketpair(AF_LOCAL, SOCK_STREAM, 0, int fd[2]);产生一对互相链接的网络套接字(文件描述符),可以用来在两个进程间进行双向通信。用于fork父子进程之间,每个进程只需要保留一个套接字,读写都用它。

专用进程间通信方式:共享内存/消息队列/信号量
System V IPC:共享内存和消息队列比较好用
POSIX IPC:信号量比较好用
共享内存 share memory sys/shm.h
shmget(key,size,flag|mode)创建或者取得一个共享内存对象,返回对象id。同一个key返回是同一个共享内存对象。当key是IPC_PRIVATE(也就是0)的时候例外,总是新建一个共享内存对象)。flag可以是0或者是IPC_CREAT或者IPC _EXCL适当组合。mode跟文件的权限一样。失败返回-1。key类似于文件路径名,甚至可以用文件路径通过函数ftok来产生key。
shmat(id,NULL, 0或者SHM_RDONLY)把共享内存挂接到本地进程的内存中,返回挂接后地址。失败返回(void*)-1。
shmdt(const void* shmaddr)解除挂载,addr是shmat返回的地址。
shmctl(id,IPC_RMID,NULL);删除一个共享内存对象。
进程间通信对象是内核对象,即使进程结束它依然存在。可以用命令ipcs查看。可以用ipcrm删除。

消息队列:message queue
msgget(key, flag | mode)创建或者取得一个消息队列对象,返回对象的id。同一个key得到同一个对象。flag | mode和shmget类似。
msgsnd(id, msg*, size, flag如果发送的数据发不出去怎么办0或者IPC_NOWAIT)打包发送一个消息数据到消息队列中。打包结构:
struct msg {
long type; // 消息类型,正整数
char data[?]; // 任意类型消息数据长度不定
};
msgrcv(id,msg*, size,type,0或者IPC_NOWAIT)从消息队列中接收一个指定类型的消息(type为0表示无论什么类型都可以),返回收到的字节数,失败-1。最后一个参数为0表示没有指定类型的消息就等待,为IPC_NOWAIT表示不等待。
msgctl(id,IPC_RMID, NULL)删除一个消息队列对象。
消息队列发送接收的时候都是指定数据部分的长度,不包括类型字段,如果加上了类型长度会导致stack被摧毁程序跑飞。

信号量
semget(key,n,flag)创建或者取得一个信号量集对象,返回id。同一个key取得同一个信号量集对象。n是信号量的个数,一般用1。flag可以是0/IPC_CREAT/IPC_EXCL跟权限的组合。
semop(id,sembuf ops[],n)对信号量集进行数组ops指定的操作,其中n是ops中元素的个数(一般是1)。信号量集里可以有若干个信号量,它们的编号从0开始(类似于数组的下标)。
struct sembuf {

unsigned short sem_num; /要操作的信号量编号,一般是0,表示第一个信号量 /
short sem_op; /* 计数操作,一般是1或者-1,表示计数器+1或者-1 */
short sem_flg; /* 0或者IPC_NOWAIT | SEM_UNDO。其中SEM_UNDO表示进程结束时系统自动复原该进程对信号量的操作 */

};
semctl(id, 0, IPC_RMID, NULL);删除一个信号量集对象
semctl(id, idx, SETVAL,N);设置下标为idx的信号量的值为N。idx一般为0。
一个信号量就是一个计数器,一般用来控制访问同一资源的进程数量,控制多个进程的同步。计数器减一操作在不够减的时候会等待,直到够减为止(信号可能会打断它)。semtimedop可以指定超时时间。

守护进程(精灵进程)
daemon(是否保持当前目录,是否保持终端文件),一般两个参数都用0。
自己实现:
(1)fork()让父进程结束
(2)关闭终端相关的三个文件
(3)重新设置当前目录(一般设为根目录或者主目录)
(4)设置umask
(5)setsid()独立建一个进程组(和一个会话)
(6)无线循环在后台做事情

0 0
原创粉丝点击