使用共享内存和记录锁实例。本例中,父进程创建一段共享内存,然后向其中追加字符串"Parent"(在写入“Parent”的时候,采用一个字符一个字符的写入,目的是为了验证记录锁对父子进程同步的正确性);子进程向共享内存中追加字符串“Child”(同样是一个一个的字符写入)。由于记录锁是针对文件的,所以得先创建一个空文件作为记录锁的操作对象,作为共享内存访问的辅助工具,如果一个进程对这个空文件加写锁成功后,就开始访问共享内存,访问结束就对文件解锁。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHM_SIZE 1024 /* shared memory size(bytes) */
#define SHM_MODE 0600 /* user read/write */
#define WRITE_LOCK(fd) regLock((fd), F_SETLKW, F_WRLCK, 0, SEEK_SET, 0)
#define UN_LOCK(fd) regLock((fd), F_SETLK, F_UNLCK, 0, SEEK_SET, 0)
/* 创建一个文件 */
int createFile()
{
int fd;
if ( (fd = open("/tmp/emptyfile4shm", O_RDWR | O_CREAT, 0666)) < 0) {
fprintf(stderr, "Create a empty file failed!\n");
exit(EXIT_FAILURE);
}
return fd;
}
/* 在文件fd上加锁或解锁*/
int regLock(int fd, int cmd, int type, off_t offset, int whence, off_t len)
{
struct flock lock;
lock.l_type = type; /* lock type: F_RDLCK, F_WRLCK, F_UNLCK */
lock.l_start = offset; /* byte offset relative to l_whence */
lock.l_whence = whence; /* it's value : SEEK_SET, SEEK_CUR, SEEK_END */
lock.l_len = len; /* bytes (0 means to EOF) */
return fcntl(fd, cmd, &lock);
}
int main(void)
{
int shmid;
int filed;
pid_t pid;
char *shmptr = NULL;
filed = createFile();
if ( (shmid = shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE)) < 0) { /* Create shared memory */
fprintf(stderr, "Create shared memory failed!\n");
exit(EXIT_FAILURE);
}
if ( (pid = fork()) < 0) { /* Create a child process */
fprintf(stderr, "Create child process failed!\n");
exit(EXIT_FAILURE);
}
if (pid == 0) { /* In child process */
if ( (shmptr = shmat(shmid, 0, 0)) == (void *)-1) {
fprintf(stderr, "Attached shared memory failed!\n");
exit(EXIT_FAILURE);
}
while (1) {
WRITE_LOCK(filed); /* add a write lock to filed */
/* shared memory 剩余的空间不能存储"Child"字符串和结束符0时就退出循环 */
if (SHM_SIZE - strlen(shmptr) < strlen("Child") + 1) break;
strcat(shmptr, "C"); /* 由于加了锁,每个Child将会连续出现 */
strcat(shmptr, "h");
strcat(shmptr, "i");
strcat(shmptr, "l");
strcat(shmptr, "d");
UN_LOCK(filed); /* release lock */
}
printf("child process:\n\t%s\n", shmptr); /* child process print shared memory */
exit(0);
}
/* In parent process */
if ( (shmptr = shmat(shmid, 0, 0)) == (void *)-1) { /* Attached shared memory */
fprintf(stderr, "Attached shared memory failed!\n");
exit(EXIT_FAILURE);
}
while (1) {
WRITE_LOCK(filed);
/* shared memory 剩余的空间不能存储"Parent"字符串和结束符0时就退出循环 */
if (SHM_SIZE - strlen(shmptr) < strlen("Parent") + 1) break;
strcat(shmptr, "P");/* 由于加了锁,每个Parent将会连续出现 */
strcat(shmptr, "a");
strcat(shmptr, "r");
strcat(shmptr, "e");
strcat(shmptr, "n");
strcat(shmptr, "t");
UN_LOCK(filed);
}
printf("parent process:\n\t%s\n", shmptr); /* parent print shared memory */
wait(0);
exit(0);
}