前些天看到有个博主写博客采用问答式的叙述方法:把很多知识点通过一问一答的形式把文章串起来,我觉得这种形式不错,便于突出重点。后面我也做下尝试,一边写写博客,一边回顾一下自己对IPC进程通信的认识。
Q:这些例子来自哪?
A:来自IBM的文档库,具体地址可以参考我的这篇文章 http://blog.youkuaiyun.com/lzx_bupt/article/details/7651207,汇总了这几天我看的进程通信的资料。
Q:IBM原文都写过了,为什么还要在这里再写一遍?
A:IBM原文挺经典的,我这里还是建议大家看看,但是原文例子有些编译不通过的地方,需要做适当修改才能运行。另外那些例子比较早了,在现在的系统上运行结果不一定和文章描述一致。最后就是,原文对例子中的语句注释不够详细,不如再写一遍,加深对例子的认识,同时多学习点编程知识。
Q:代码里怎么那么多注释?
A:我本来想少写点注释的,并且打算用自己的话写,不过我发现系统编程手册给的解释特别好,而且已经很精简了,其他网站给的说明还没有手册的完整,所以干脆直接贴手册的内容吧。所以会看到注释比代码还多。。。,如果你不想看注释,直接把代码粘到本地,删除注释就一目了然了。
Q:例子能保证编译么,可以开始了?
A:都是自己编译通过的,让我们开始吧~
IPC共享内存-----系统V方式编程实例
该实例包含两个程序:map_v_write.cpp和map_v_read.cpp,分别编译后先创建一个文件名为myshm,这个文件是生成IPC KEY而用的,代码里有描述。之后先运行write程序,再运行read程序,观察结果。
/* 文件:map_v_write.cpp
描述:和map_v_read.cpp文件配合完成系统V共享内存编程实验
*/
//#include <sys/ipc.h>
//#include <sys/types.h>//注释掉的两个头文件是IPC最基本的,但在shm.h中include过了
#include <sys/shm.h>//系统V共享内存函数shmget shmat shmdt
#include <string.h>//memcpy
#include <stdio.h>//perror
#include <errno.h>//errno
//共享内存通信多采用结构体数据表达信息,任意定义
typedef struct{
char name[4];
int age;
}people;
main(int argc, char** argv)
{
int shm_id,i;
key_t key;//保存ftok函数返回值
char temp;
people *p_map;
//创建IPC键值
char* name = "./myshm";//务必指定存在的文件
key = ftok(name, 1);//参数尽量别用0
/* man ftok:
NAME
ftok - generate an IPC key
SYNOPSIS
#include <sys/ipc.h>
key_t ftok(const char *path, int id);
DESCRIPTION
The ftok() function returns a key based on path and id that
is usable in subsequent calls to msgget(2), semget(2) and
shmget(2). The path argument must be the pathname of an
existing file that the process is able to stat(2).
The ftok() function will return the same key value for all
paths that name the same file, when called with the same id
value, and will return different key values when called with
different id values.
If the file named by path is removed while still referred to
by a key, a call to ftok() with the same path and id returns
an error. If the same file is recreated, then a call to
ftok() with the same path and id is likely to return a dif-
ferent key.
Only the low order 8-bits of id are significant. The
behavior of ftok() is unspecified if these bits are 0.
RETURN VALUES
Upon successful completion, ftok() returns a key. Other-
wise, ftok() returns (key_t)-1 and sets errno to indicate
the error.
*/
perror("ftok:");//打印errno, 参考附录errno定义
/* man perror
NAME
perror, errno - print system error messages
SYNOPSIS
#include <stdio.h>
void perror(const char *s);
#include <errno.h>
int errno;
DESCRIPTION
The perror() function produces a message on the standard
error output (file descriptor 2) describing the last error
encountered during a call to a system or library function.
The argument string s is printed, followed by a colon and a
blank, followed by the message and a NEWLINE character. If
s is a null pointer or points to a null string, the colon is
not printed. The argument string should include the name of
the program that incurred the error. The error number is
taken from the external variable errno, which is set when
errors occur but not cleared when non-erroneous calls are
made. See intro(2).
*/
//获取共享内存ID
shm_id=shmget(key,4096,IPC_CREAT|00666);//give the permissions
perror("shmget:");
/* man shmget:
NAME
shmget - get shared memory segment identifier
SYNOPSIS
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
DESCRIPTION
The shmget() function returns the shared memory identifier
associated with key.
A shared memory identifier and associated data structure and
shared memory segment of at least size bytes (see intro(2))
are created for key if one of the following are true:
o The key argument is equal to IPC_PRIVATE.
o The key argument does not already have a shared memory
identifier associated with it, and (shmflg&IPC_CREAT)
is true.
Upon creation, the data structure associated with the new
shared memory identifier is initialized as follows:
o The values of shm_perm.cuid, shm_perm.uid,
shm_perm.cgid, and shm_perm.gid are set equal to the
effective user ID and effective group ID, respec-
tively, of the calling process.
o The access permission bits of shm_perm.mode are set
equal to the access permission bits of shmflg.
shm_segsz is set equal to the value of size.
o The values of shm_lpid, shm_nattch shm_atime, and
shm_dtime are set equal to 0.
o The shm_ctime is set equal to the current time.
Shared memory segments must be explicitly removed after the
last reference to them has been removed.
RETURN VALUES
Upon successful completion, a non-negative integer
representing a shared memory identifier is returned. Other-
wise, -1 is returned and errno is set to indicate the error.
*/
p_map=(people*)shmat(shm_id,NULL,0);
perror("shmat:");
/*
NAME
shmop, shmat, shmdt - shared memory operations
SYNOPSIS
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
Default
int shmdt(char *shmaddr);
Standard conforming
int shmdt(const void *shmaddr);
DESCRIPTION
The shmat() function attaches the shared memory segment
associated with the shared memory identifier specified by
shmid to the data segment of the calling process.
*/
//往内存写入数据
temp='a';
for(i = 0;i<10;i++)
{
temp+=1;
memcpy((*(p_map+i)).name,&temp,1);
(*(p_map+i)).age=20+i;
}
//unlink共享内存
shmdt((char*)p_map);//这里可以去掉char*编译试试,我这里去掉后编译不通过,待研究
perror("shmdt:");
/*
The shmdt() function detaches from the calling process's
data segment the shared memory segment located at the
address specified by shmaddr. If the application is
standard-conforming (see standards(5)), the shmaddr argument
is of type const void *. Otherwise it is of type char *.
*/
}
读端的程序用到的API和写端一样,就略去注释了
/* 文件:map_v_read.cpp
描述:和map_v_write.cpp文件配合完成系统V共享内存编程实验
*/
#include <sys/shm.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
//读端程序要和写端程序保持一致,这样才能互相通信
//定义数据结构
typedef struct{
char name[4];
int age;
} people;
main(int argc, char** argv)
{
int shm_id,i;
key_t key;
people *p_map;
//create shm file and get key
char* name = "./myshm";
key = ftok(name,1);
perror("ftok:");
//get shm
shm_id = shmget(key,4096,IPC_CREAT);
perror("shmget:");
//link the shm
p_map = (people*)shmat(shm_id,NULL,0);
perror("shmat:");
for(i = 0;i<10;i++)
{
printf( "name:%s\n",(*(p_map+i)).name );
printf( "age %d\n",(*(p_map+i)).age );
}
//unlink
shmdt((char*)p_map);
perror("shmdt:");
}
最后贴一下errno.h定义,据此可以找到错误原因
#define EPERM 1 /* Not super-user */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Arg list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No children */
#define EAGAIN 11 /* Resource temporarily unavailable */
#define ENOMEM 12 /* Not enough core */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Mount device busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Inappropriate ioctl for device */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math arg out of domain of func */
#define ERANGE 34 /* Math result not representable */
#define ENOMSG 35 /* No message of desired type */
#define EIDRM 36 /* Identifier removed */
#define ECHRNG 37 /* Channel number out of range */
#define EL2NSYNC 38 /* Level 2 not synchronized */
#define EL3HLT 39 /* Level 3 halted */
#define EL3RST 40 /* Level 3 reset */
#define ELNRNG 41 /* Link number out of range */
#define EUNATCH 42 /* Protocol driver not attached */
#define ENOCSI 43 /* No CSI structure available */
#define EL2HLT 44 /* Level 2 halted */
#define EDEADLK 45 /* Deadlock condition. */
#define ENOLCK 46 /* No record locks available. */
#define ECANCELED 47 /* Operation canceled */
#define ENOTSUP 48 /* Operation not supported */
/* Filesystem Quotas */
#define EDQUOT 49 /* Disc quota exceeded */
/* Convergent Error Returns */
#define EBADE 50 /* invalid exchange */
#define EBADR 51 /* invalid request descriptor */
#define EXFULL 52 /* exchange full */
#define ENOANO 53 /* no anode */
#define EBADRQC 54 /* invalid request code */
#define EBADSLT 55 /* invalid slot */
#define EDEADLOCK 56 /* file locking deadlock error */
#define EBFONT 57 /* bad font file fmt */
/* Interprocess Robust Locks */
#define EOWNERDEAD 58 /* process died with the lock */
#define ENOTRECOVERABLE 59 /* lock is not recoverable */
/* stream problems */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* no data (for no delay io) */
#define ETIME 62 /* timer expired */
#define ENOSR 63 /* out of streams resources */
#define ENONET 64 /* Machine is not on the network */
#define ENOPKG 65 /* Package not installed */
#define EREMOTE 66 /* The object is remote */
#define ENOLINK 67 /* the link has been severed */
#define EADV 68 /* advertise error */
#define ESRMNT 69 /* srmount error */
#define ECOMM 70 /* Communication error on send */
#define EPROTO 71 /* Protocol error */
/* Interprocess Robust Locks */
#define ELOCKUNMAPPED 72 /* locked lock was unmapped */
#define ENOTACTIVE 73 /* Facility is not active */
#define EMULTIHOP 74 /* multihop attempted */
#define EBADMSG 77 /* trying to read unreadable message */
#define ENAMETOOLONG 78 /* path name is too long */
#define EOVERFLOW 79 /* value too large to be stored in data type */
#define ENOTUNIQ 80 /* given log. name not unique */
#define EBADFD 81 /* f.d. invalid for this operation */
#define EREMCHG 82 /* Remote address changed */
/* shared library problems */
#define ELIBACC 83 /* Can't access a needed shared lib. */
#define ELIBBAD 84 /* Accessing a corrupted shared lib. */
#define ELIBSCN 85 /* .lib section in a.out corrupted. */
#define ELIBMAX 86 /* Attempting to link in too many libs. */
#define ELIBEXEC 87 /* Attempting to exec a shared library. */
#define EILSEQ 88 /* Illegal byte sequence. */
#define ENOSYS 89 /* Unsupported file system operation */
#define ELOOP 90 /* Symbolic link loop */
#define ERESTART 91 /* Restartable system call */
#define ESTRPIPE 92 /* if pipe/FIFO, don't sleep in stream head */
#define ENOTEMPTY 93 /* directory not empty */
#define EUSERS 94 /* Too many users (for UFS) */
/* BSD Networking Software */
/* argument errors */
#define ENOTSOCK 95 /* Socket operation on non-socket */
#define EDESTADDRREQ 96 /* Destination address required */
#define EMSGSIZE 97 /* Message too long */
#define EPROTOTYPE 98 /* Protocol wrong type for socket */
#define ENOPROTOOPT 99 /* Protocol not available */
#define EPROTONOSUPPORT 120 /* Protocol not supported */
#define ESOCKTNOSUPPORT 121 /* Socket type not supported */
#define EOPNOTSUPP 122 /* Operation not supported on socket */
#define EPFNOSUPPORT 123 /* Protocol family not supported */
#define EAFNOSUPPORT 124 /* Address family not supported by */
/* protocol family */
#define EADDRINUSE 125 /* Address already in use */
#define EADDRNOTAVAIL 126 /* Can't assign requested address */
/* operational errors */
#define ENETDOWN 127 /* Network is down */
#define ENETUNREACH 128 /* Network is unreachable */
#define ENETRESET 129 /* Network dropped connection because */
/* of reset */
#define ECONNABORTED 130 /* Software caused connection abort */
#define ECONNRESET 131 /* Connection reset by peer */
#define ENOBUFS 132 /* No buffer space available */
#define EISCONN 133 /* Socket is already connected */
#define ENOTCONN 134 /* Socket is not connected */
/* XENIX has 135 - 142 */
#define ESHUTDOWN 143 /* Can't send after socket shutdown */
#define ETOOMANYREFS 144 /* Too many references: can't splice */
#define ETIMEDOUT 145 /* Connection timed out */
#define ECONNREFUSED 146 /* Connection refused */
#define EHOSTDOWN 147 /* Host is down */
#define EHOSTUNREACH 148 /* No route to host */
#define EWOULDBLOCK EAGAIN
#define EALREADY 149 /* operation already in progress */
#define EINPROGRESS 150 /* operation now in progress */
/* SUN Network File System */
#define ESTALE 151 /* Stale NFS file handle */