几种方式
●talk命令
功能:talk可以同时等待两个文件描述符的输入,读取字符并将它们写到目的地。
实现:不能像下面这样,因为read会阻塞直到有输入,可能在第一个read处就挂起。使用非阻塞的方式可以工作,但是占用太多处理器时间。因为每次调用read都是一个系统调用,程序就必须回到内核模式工作,在等待一个字符来之前可能切换上千次。
●select系统调用:允许程序挂起,并等待从不止一个文件描述符的输入。
/* selectdemo.c : watch for input on two devices AND timeout
* usage: selectdemo dev1 dev2 timeout
* action: reports on input from each file, and
* reports timeouts
*/
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#define oops(m,x) { perror(m); exit(x); }
void showdata(char*,int);
int main(int ac, char *av[])
{
int fd1, fd2; /* the fds to watch */
struct timeval timeout; /* how long to wait */
fd_set readfds; /* watch these for input */
int maxfd; /* max fd plus 1 */
int retval; /* return from select */
if ( ac != 4 ){
fprintf(stderr,"usage: %s file file timeout", *av);
exit(1);
}
/** open files **/
if ( (fd1 = open(av[1],O_RDONLY)) == -1 )
oops(av[1], 2);
if ( (fd2 = open(av[2],O_RDONLY)) == -1 )
oops(av[2], 3);
maxfd = 1 + (fd1>fd2?fd1:fd2);
while(1) {
/** make a list of file descriptors to watch **/
FD_ZERO(&readfds); /* clear all bits */
FD_SET(fd1, &readfds); /* set bit for fd1 */
FD_SET(fd2, &readfds); /* set bit for fd2 */
/** set timeout value **/
timeout.tv_sec = atoi(av[3]); /* set seconds */
timeout.tv_usec = 0; /* no useconds */
/** wait for input **/
retval = select(maxfd,&readfds,NULL,NULL,&timeout);
if( retval == -1 )
oops("select",4);
if ( retval > 0 ){
/** check bits for each fd **/
if ( FD_ISSET(fd1, &readfds) )
showdata(av[1], fd1);
if ( FD_ISSET(fd2, &readfds) )
showdata(av[2], fd2);
}
else
printf("no input after %d seconds\n", atoi(av[3]));
}
}
void showdata(char *fname, int fd)
{
char buf[BUFSIZ];
int n;
printf("%s: ", fname, n);
fflush(stdout);
n = read(fd, buf, BUFSIZ);
if ( n == -1 )
oops(fname,5);
write(1, buf, n);
write(1, "\n", 1);
}
●通过文件的进程间通信
●命名管道
通常管道只能连接相关的进程,而使用命名管道可以连接不相关的进程,并且可以独立于进程存在
●共享内存:共享内存段对于进程而言,就类似于共享变量对于线程一样。
共享内存时间服务器代码,客户改成读内存
/* shm_ts.c : the time server using shared memory, a bizarre application */
#include <stdio.h>
#include <sys/shm.h>
#include <time.h>
#define TIME_MEM_KEY 99 /* like a filename */
#define SEG_SIZE ((size_t)100) /* size of segment */
#define oops(m,x) { perror(m); exit(x); }
main()
{
int seg_id;
char *mem_ptr, *ctime();
long now;
int n;
/* create a shared memory segment */
seg_id = shmget( TIME_MEM_KEY, SEG_SIZE, IPC_CREAT|0777 );
if ( seg_id == -1 )
oops("shmget", 1);
/* attach to it and get a pointer to where it attaches */
mem_ptr = shmat( seg_id, NULL, 0 );
if ( mem_ptr == ( void *) -1 )
oops("shmat", 2);
/* run for a minute */
for(n=0; n<60; n++ ){
time( &now ); /* get the time */
strcpy(mem_ptr, ctime(&now)); /* write to mem */
sleep(1); /* wait a sec */
}
/* now remove it */
shmctl( seg_id, IPC_RMID, NULL );
}
如何选择
进程间访问共享资源
●文件锁
进程可以忽略锁机制
●信号量
信号量是一个内核变量,可以被系统中的任何进程访问,进程间可以使用这个变量来协调对于共享内存和其他资源的访问。
纵观IPC:各种方式的特点,见书490