Chinaunix首页 | 论坛 | 博客
  • 博客访问: 305270
  • 博文数量: 69
  • 博客积分: 352
  • 博客等级: 入伍新兵
  • 技术积分: 296
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-16 15:41
文章分类
文章存档

2023年(1)

2021年(1)

2020年(2)

2017年(4)

2016年(3)

2015年(1)

2013年(1)

2012年(21)

2011年(35)

分类:

2011-12-19 17:00:03

Outline 

        - 1.
pipe使用框架

        - 2.
fifo使用框架

        - 3.
file lock使用框架

        - 
4.semaphore使用框架

        - 
5.shared memory使用框架

        - 
6.memory mapped file使用框架

        - 
7.unix socket使用框架

=============================================================
1. pipe使用框架:
实现 "ls | wc -l"
int pipefd[2];
pipe(pipefd);
if(!fork()) {
  close(pipefd[0]);
  dup2(pipefd[1], 1);
  execlp("ls", "ls", NULL);
  exit(0);
} else {
  wait(NULL);
  close(pipefd[1]);
  dup2(pipefd[0], 0);
  execlp("wc", "wc", "-l", NULL);
  exit(0);
}
注:一般pipe大小为10K
 
2. fifo使用框架
实现echo writer reader,即writer在fifo中写,reader在fifo中读并回显
writer:
mknod("fifoname", S_FIFO | 0666, 0);
fd = open("fifoname", O_WRONLY);
write(fd, input, sizeof(input));
//unlink("fifoname");
 
reader:
fd = open("fifoname", O_RDONLY);
read(fd, output, sizeof(output));
printf("%s", output);
 
注意:若reader先关闭,则writer在执行write时收到sigpipe信号;反之,reader执行reader时返回0.
open在没有读者/写者时候,都见先阻塞,直到第一个读者/写者到来.

3. file lock使用框架
所谓file lock,就是对文件加读/写锁,读写锁的原则是一个文件可以有多个读者(没有写者),但是只能有一个写者(没有读者)。具体到程序即,获取多个读锁不会阻塞,但是获取多个写锁会阻塞;有读者时,获取写锁会阻塞;有写者时,获取读锁会阻塞。

下面这个例子,有参数时,给文件加读锁;无参数时,给文件加写锁。按回车后,释放锁。
  1. /*
  2.  * =====================================================================================
  3.  *
  4.  * Filename: rw_locks.c
  5.  *
  6.  * Description:
  7.  *
  8.  * Version: 1.0
  9.  * Created: 08/10/11 13:14:57
  10.  * Revision: none
  11.  * Compiler: gcc
  12.  *
  13.  * Author: YOUR NAME (),
  14.  * Company:
  15.  *
  16.  * =====================================================================================
  17.  */
  18. #include <stdio.h>
  19. #include <error.h>
  20. #include <fcntl.h>
  21. #include <unistd.h>

  22. int main(int argc, char *argv[])
  23. {
  24.     int fd;
  25.     struct flock flock;

  26.     flock.l_type = F_WRLCK; //锁的模式必须与文件打开模式显适应
  27.     flock.l_whence = SEEK_SET;
  28.     flock.l_start = 0;
  29.     flock.l_len = 0;
  30.     flock.l_pid = getpid();

  31.     fd = open("tt", O_RDWR);
  32.     if (fd == -1) {
  33.         perror("open file error");
  34.         return -1;
  35.     }

  36.     if(argc > 1)
  37.         flock.l_type = F_RDLCK;

  38.     printf("Trying to obtain a %s lock!\n",
  39.                     flock.l_type == F_RDLCK ? "read_lock" : "write lock");

  40.     if (fcntl(fd, F_SETLKW, &flock) == -1) {
  41.         perror("fcntl error");
  42.         return -1;
  43.     }

  44.     printf("Got a lock!\n");
  45.     printf("Press to release the lock\n");
  46.     getchar();

  47.     flock.l_type = F_UNLCK; //UNLOCK
  48.     if (fcntl(fd, F_SETLK, &flock)) { //F_SETLK 用于解锁,也可用于加锁,但与F_SETLKW的区别在于不会被阻塞,立即返回-1
  49.         perror("fcntl error");
  50.         return -1;
  51.     }
  52.     printf("Lock released!\n");

  53.     close(fd);

  54.     return 0;
  55. }

3. mseeage queue使用框架
ftok("filename", 'A') //存在的文件名加任意int产生key
msgget //IPC_CREAT
msgsnd / msgrcv
//msgctl(id, IPC_RMID, NULL)
注:可存在多个读写者

4. semaphore使用框架
semapore中要特别注意的一点是semaphore set创建以后需要进行初始化(semop),在初始化完成前(通过检查semid_ds中的sem_otime域),其他使用该set的进程需要等待
  1. #include <stdio.h>
  2. #include <error.h>
  3. #include <unistd.h>
  4. #include <sys/sem.h>
  5. #include <sys/ipc.h>
  6. #include <sys/types.h>
  7. #include <sys/ipc.h>

  8. #define SEMNUM 1

  9. int main(int argc, char *argv[])
  10. {
  11.     key_t key;
  12.     int semid;
  13.     struct sembuf buf = {0, 1, 0};

  14.     key = ftok("tt", 'A');
  15.     if (key == -1) {
  16.         perror("ftok error");
  17.         return -1;
  18.     }

  19.     semid = semget(key, SEMNUM, IPC_CREAT | IPC_EXCL | 0666);
  20.     if (semid == -1) {
  21.         perror("semget error");
  22.         return -1;
  23.     }

  24.     puts("initialize the semaphore set...");
  25.     puts("press to continue");
  26.     getchar();
  27.     for (buf.sem_num = 0; buf.sem_num < SEMNUM; buf.sem_num++) {
  28.         if (semop(semid, &buf, 1) == -1) {
  29.             perror("semop error");
  30.             semctl(semid, 0, IPC_RMID);
  31.             return -1;
  32.         }
  33.     }

  34.     //-----------------------------------
  35.     
  36.     buf.sem_num = 0;
  37.     buf.sem_op = -1;
  38.     buf.sem_flg = 0;

  39.     puts("Acquire a resource");
  40.     if (semop(semid, &buf, 1) == -1) {
  41.         perror("semop error");
  42.         return -1;
  43.     }
  44.     puts("Resource locked");

  45.     puts("Press to unlock");
  46.     getchar();
  47.     
  48.     buf.sem_op = 1;
  49.     if (semop(semid, &buf, 1) == -1) {
  50.         perror("semop error");
  51.         return -1;
  52.     }
  53.     puts("Resource unlocked");

  54.     puts("Press to destroy");
  55.     getchar();
  56.     if (semctl(semid, 0, IPC_RMID) == -1) {
  57.         perror("semctl error");
  58.         return -1;
  59.     }

  60.     return 0;
  61. }

  1. #include <stdio.h>
  2. #include <error.h>
  3. #include <sys/sem.h>
  4. #include <sys/types.h>
  5. #include <sys/ipc.h>
  6. #include <unistd.h>
  7. #include <stdlib.h>
  8. #include <errno.h>

  9. int main()
  10. {
  11.     key_t key;
  12.     int semid;
  13.     union semun{
  14.         int val;
  15.         struct semid_ds *buf;
  16.         unsigned short *array;
  17.         struct seminfo *__buf;
  18.     }arg;
  19.     struct sembuf buf;
  20.     struct semid_ds ds;
  21.     
  22.     key = ftok("tt", 'A');
  23.     if (key == -1) {
  24.         perror("ftok error");
  25.         return -1;
  26.     }

  27.     semid = semget(key, 1, IPC_CREAT | IPC_EXCL );
  28.     
  29.     puts("waiting for initialization");

  30.     if (semid == -1) {
  31.         if (errno == EEXIST) {
  32.             while(1) {
  33.                 semid = semget(key, 1, 0666);
  34.                 if (semid < 0) {
  35.                     perror("semget error");
  36.                     return -1;
  37.                 }
  38.                 
  39.                 arg.buf = &ds;
  40.                 if (semctl(semid, 0, IPC_STAT, arg) == -1) {
  41.                     perror("semctl1 error");
  42.                     //return -1;
  43.                 }
  44.             
  45.             if (arg.buf->sem_otime != 0)
  46.                 break;
  47.             }
  48.         } else {
  49.             perror("semget2 error");
  50.             return -1;
  51.         }
  52.     }

  53.     puts("initialization is done");

  54.     puts("locking resource");

  55.     buf.sem_num = 0;
  56.     buf.sem_op = -1;
  57.     buf.sem_flg = 0;

  58.     if (semop(semid, &buf, 1) == -1) {
  59.         perror("semop error");
  60.         return -1;
  61.     }

  62.     puts("Resource locked");

  63.     puts("press to unlock");
  64.     getchar();

  65.     buf.sem_op = 1;

  66.     if (semop(semid, &buf, 1) == -1) {
  67.         perror("semop error");
  68.         return -1;
  69.     }

  70.     puts("Resource unlocked");

  71.     return 0;
  72. }

5. shared memory使用框架
ftok
shmget //IPC_CREAT
data = shmat(id, (void *)0, 0)
//do sth with the return pointer
shmdt
//shmctl(id, IPC_RMID, NULL)

6. memory mapped file使用框架
open
data = mmap((void *)0, statbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)
read / write
munmap(data, statbuf.st_size)

注意,若使用MAP_PRIVATE则各进程分别获取file的一份拷贝,并且最终修改不会写入文件中

7. unix socket使用框架
sockaddr_un local;

local.sun_family = AF_UNIX;
strcpy(local.sun_path, "/a/b/c")

server端
fd = socket(...)
unlink("a/b/c")
bind
listen
newfd = accept
recv / send
close

client端
fd=socket(...)
unlink("/a/b/c")
connect
send / recv
close
阅读(1696) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~