前些天看到有个博主写博客采用问答式的叙述方法:把很多知识点通过一问一答的形式把文章串起来,我觉得这种形式不错,便于突出重点。后面我也做下尝试,一边写写博客,一边回顾一下自己对IPC进程通信的认识。
Q:这些例子来自哪?
A:来自IBM的文档库,具体地址可以参考我的这篇文章 http://blog.csdn.net/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程序,观察结果。
[cpp] view plaincopy
- /* 文件:map_v_write.cpp
- 描述:和map_v_read.cpp文件配合完成系统V共享内存编程实验
- */
- //#include
- //#include //注释掉的两个头文件是IPC最基本的,但在shm.h中include过了
- #include //系统V共享内存函数shmget shmat shmdt
- #include //memcpy
- #include //perror
- #include //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
- 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
- void perror(const char *s);
- #include
- 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
- #include
- #include
- 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
- #include
- 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和写端一样,就略去注释了
[cpp] view plaincopy
- /* 文件:map_v_read.cpp
- 描述:和map_v_write.cpp文件配合完成系统V共享内存编程实验
- */
- #include
- #include
- #include
- #include
- //读端程序要和写端程序保持一致,这样才能互相通信
- //定义数据结构
- 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定义,据此可以找到错误原因
[cpp] view plaincopy
- #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 */