Changeset 16
- Timestamp:
- 09/06/07 13:03:56
(1 year ago)
- Author:
- tmiller
- Message:
New simpler API where the shm segment is created in the helper process.
This came out of (and at the request of) discussions with the SIPC consumers.
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r4 |
r16 |
|
| 30 | 30 | typedef struct sipc_msg sipc_msg_t; |
|---|
| 31 | 31 | |
|---|
| | 32 | /* SIPC roles */ |
|---|
| | 33 | #define SIPC_CREATOR 0 |
|---|
| | 34 | #define SIPC_SENDER 1 |
|---|
| | 35 | #define SIPC_RECEIVER 2 |
|---|
| | 36 | |
|---|
| 32 | 37 | /* IPC types */ |
|---|
| 33 | 38 | #define SIPC_SYSV_SHM 0 |
|---|
| … | … | |
| 35 | 40 | #define SIPC_NUM_TYPES 2 |
|---|
| 36 | 41 | |
|---|
| 37 | | /* sipc_init(char *key, enum sipc_types ipc_type, int sender) |
|---|
| | 42 | /* sipc_open(char *key, int role, int ipc_type, size_t size) |
|---|
| 38 | 43 | * key Unique key to identify IPC communication channel, |
|---|
| 39 | 44 | * must be the same for the sender and reciever. |
|---|
| 40 | | * ipc_types Which IPC type used, must be the same for sender |
|---|
| | 45 | * role SIPC_CREATOR if this application is the IPC creator, |
|---|
| | 46 | * SIPC_SENDER for the sender and SIPC_RECEIVER |
|---|
| | 47 | * for the reciever |
|---|
| | 48 | * ipc_type Which IPC type used, must be the same for sender |
|---|
| 41 | 49 | * and reciever. |
|---|
| 42 | | * sender 1 if this application is the IPC sender, 0 |
|---|
| 43 | | * for the reciever |
|---|
| | 50 | * size Maximum message size to be transmitted. |
|---|
| 44 | 51 | * |
|---|
| 45 | | * sipc_init must be called before any other function to initialize |
|---|
| 46 | | * the sipc_t struct. The returned pointer can be reused after |
|---|
| 47 | | * disconnecting. Caller must call sipc_destroy to free the memory. |
|---|
| | 52 | * sipc_open must be called before any other function to initialize |
|---|
| | 53 | * the sipc_t struct. Caller must call sipc_close to free the memory. |
|---|
| 48 | 54 | */ |
|---|
| 49 | | sipc_t *sipc_init(char *key, const int ipc_type, size_t size, int sender); |
|---|
| | 55 | sipc_t *sipc_open(char *key, int role, int ipc_type, size_t size); |
|---|
| 50 | 56 | |
|---|
| 51 | 57 | /* Free the sipc struct and its contents */ |
|---|
| 52 | | void sipc_destroy_handle(sipc_t *sipc); |
|---|
| | 58 | void sipc_close(sipc_t *sipc); |
|---|
| 53 | 59 | |
|---|
| 54 | 60 | /* Called by a helper application to destroy an IPC resource. |
|---|
| 55 | 61 | * This function should *NOT* be called by normal users of the library. */ |
|---|
| 56 | | void sipc_destroy_resource(char *key, int ipc_type); |
|---|
| 57 | | |
|---|
| 58 | | /* Called by a helper application to create an IPC resource. |
|---|
| 59 | | * This function should *NOT* be called by normal users of the library. */ |
|---|
| 60 | | int sipc_create(char *key, int ipc_type); |
|---|
| 61 | | |
|---|
| 62 | | /* Connect to IPC resource. sipc must already be initialized via sipc_init |
|---|
| 63 | | * returns 0 on success, non-0 on failure */ |
|---|
| 64 | | int sipc_connect(sipc_t *sipc); |
|---|
| 65 | | |
|---|
| 66 | | /* Disconnect from an IPC resource. sipc can be reused after a disconnection. |
|---|
| 67 | | * returns 0 on success, <0 on failure */ |
|---|
| 68 | | void sipc_disconnect(sipc_t *sipc); |
|---|
| | 62 | void sipc_unlink(char *key, int ipc_type); |
|---|
| 69 | 63 | |
|---|
| 70 | 64 | /* Blocking call to send msglen bytes of data. |
|---|
| … | … | |
| 91 | 85 | |
|---|
| 92 | 86 | #endif |
|---|
| 93 | | |
|---|
| r4 |
r16 |
|
| 1 | 1 | { |
|---|
| 2 | 2 | global: |
|---|
| 3 | | sipc_init; sipc_destroy_handle; |
|---|
| 4 | | sipc_create; sipc_destroy_resource; |
|---|
| 5 | | sipc_connect; sipc_disconnect; |
|---|
| 6 | | sipc_send_data; sipc_recv_data; |
|---|
| | 3 | sipc_open; |
|---|
| | 4 | sipc_close; |
|---|
| | 5 | sipc_unlink; |
|---|
| | 6 | sipc_send_data; |
|---|
| | 7 | sipc_recv_data; |
|---|
| 7 | 8 | sipc_get_data_ptr; |
|---|
| 8 | 9 | sipc_shm_recv_done; |
|---|
| r12 |
r16 |
|
| 41 | 41 | |
|---|
| 42 | 42 | msqid = msgget(key, MQ_PERMS|IPC_CREAT|IPC_EXCL); |
|---|
| 43 | | if (msqid < 0) { |
|---|
| | 43 | if (msqid < 0) |
|---|
| 44 | 44 | fprintf(stderr, "msgget: %s\n", strerror(errno)); |
|---|
| 45 | | return -1; |
|---|
| 46 | | } |
|---|
| 47 | 45 | |
|---|
| 48 | | return 0; |
|---|
| | 46 | return msqid; |
|---|
| 49 | 47 | } |
|---|
| 50 | 48 | |
|---|
| … | … | |
| 66 | 64 | } |
|---|
| 67 | 65 | |
|---|
| 68 | | int hidden mqueue_connect(key_t key, int sender) |
|---|
| | 66 | int hidden mqueue_connect(key_t key, int role) |
|---|
| 69 | 67 | { |
|---|
| 70 | | int flags = 0, msqid = 0; |
|---|
| 71 | | flags = sender ? 0200 : 0400; |
|---|
| | 68 | int flags, msqid; |
|---|
| | 69 | |
|---|
| | 70 | switch (role) { |
|---|
| | 71 | case SIPC_SENDER: |
|---|
| | 72 | flags = 0200; |
|---|
| | 73 | break; |
|---|
| | 74 | case SIPC_RECEIVER: |
|---|
| | 75 | flags = 0400; |
|---|
| | 76 | break; |
|---|
| | 77 | default: |
|---|
| | 78 | return -1; |
|---|
| | 79 | } |
|---|
| 72 | 80 | |
|---|
| 73 | 81 | msqid = msgget(key, flags); |
|---|
| r4 |
r16 |
|
| 1 | 1 | /* Author: Joshua Brindle <jbrindle@tresys.com> |
|---|
| 2 | 2 | * David Windsor <dwindsor@tresys.com> |
|---|
| 3 | | * |
|---|
| | 3 | * |
|---|
| 4 | 4 | * Copyright (C) 2006, 2007 Tresys Technology, LLC |
|---|
| 5 | 5 | * Developed Under US JFCOM Sponsorship |
|---|
| … | … | |
| 34 | 34 | }; |
|---|
| 35 | 35 | |
|---|
| 36 | | sipc_t *sipc_init(char *key, const int ipc_type, size_t len, int sender) |
|---|
| | 36 | sipc_t *sipc_open(char *key, int role, int ipc_type, size_t len) |
|---|
| 37 | 37 | { |
|---|
| 38 | 38 | sipc_t *new_sipc = NULL; |
|---|
| 39 | 39 | key_t sipc_key; |
|---|
| 40 | | |
|---|
| 41 | | new_sipc = calloc(1, sizeof(sipc_t)); |
|---|
| 42 | | if (!new_sipc) |
|---|
| 43 | | goto err; |
|---|
| 44 | 40 | |
|---|
| 45 | 41 | if (ipc_type >= SIPC_NUM_TYPES || ipc_type < 0) |
|---|
| … | … | |
| 53 | 49 | } |
|---|
| 54 | 50 | |
|---|
| | 51 | new_sipc = calloc(1, sizeof(sipc_t)); |
|---|
| | 52 | if (!new_sipc) |
|---|
| | 53 | goto err; |
|---|
| 55 | 54 | new_sipc->key = sipc_key; |
|---|
| 56 | 55 | new_sipc->ipc_type = ipc_type; |
|---|
| 57 | | new_sipc->sender = sender; |
|---|
| | 56 | new_sipc->role = role; |
|---|
| 58 | 57 | new_sipc->len = len; |
|---|
| 59 | 58 | new_sipc->msg_len = SIPC_MSGLEN_NOT_SET; |
|---|
| 60 | 59 | |
|---|
| 61 | | /* call backend specific init to fill in function table */ |
|---|
| | 60 | /* call backend specific init to fill in function table */ |
|---|
| 62 | 61 | if (sipc_init_f[ipc_type](new_sipc)) |
|---|
| 63 | 62 | goto err; |
|---|
| 64 | | |
|---|
| | 63 | |
|---|
| | 64 | /* |
|---|
| | 65 | * Create the underlying ipc object or attach to an existing |
|---|
| | 66 | * one depending on what role we are playing. |
|---|
| | 67 | */ |
|---|
| | 68 | switch (role) { |
|---|
| | 69 | case SIPC_CREATOR: |
|---|
| | 70 | if (new_sipc->funcs->sipc_create(new_sipc) < 0) |
|---|
| | 71 | goto err; |
|---|
| | 72 | break; |
|---|
| | 73 | case SIPC_SENDER: |
|---|
| | 74 | case SIPC_RECEIVER: |
|---|
| | 75 | if (new_sipc->funcs->sipc_attach(new_sipc) < 0) |
|---|
| | 76 | goto err; |
|---|
| | 77 | break; |
|---|
| | 78 | default: |
|---|
| | 79 | goto err; |
|---|
| | 80 | } |
|---|
| | 81 | |
|---|
| 65 | 82 | return new_sipc; |
|---|
| 66 | 83 | err: |
|---|
| … | … | |
| 69 | 86 | } |
|---|
| 70 | 87 | |
|---|
| 71 | | void sipc_destroy_handle(sipc_t *sipc) |
|---|
| | 88 | void sipc_close(sipc_t *sipc) |
|---|
| 72 | 89 | { |
|---|
| 73 | 90 | if (!sipc) |
|---|
| 74 | 91 | return; |
|---|
| 75 | 92 | |
|---|
| 76 | | sipc->funcs->sipc_destroy_handle(sipc); |
|---|
| | 93 | sipc->funcs->sipc_detach(sipc); |
|---|
| 77 | 94 | free(sipc); |
|---|
| 78 | 95 | } |
|---|
| 79 | 96 | |
|---|
| 80 | | void sipc_destroy_resource(char *key, int ipc_type) |
|---|
| | 97 | void sipc_unlink(char *key, int ipc_type) |
|---|
| 81 | 98 | { |
|---|
| 82 | 99 | key_t sipc_key; |
|---|
| … | … | |
| 86 | 103 | fprintf(stderr, "ftok: %s\n", strerror(errno)); |
|---|
| 87 | 104 | return; |
|---|
| 88 | | } |
|---|
| | 105 | } |
|---|
| 89 | 106 | |
|---|
| 90 | | /* Choose which type of IPC resource we create */ |
|---|
| 91 | | switch (ipc_type) { |
|---|
| | 107 | /* XXX - if we can require an sipc * we can avoid hard-coding */ |
|---|
| | 108 | /* Choose which type of IPC resource to destroy */ |
|---|
| | 109 | switch (ipc_type) { |
|---|
| 92 | 110 | case SIPC_SYSV_MQUEUES: |
|---|
| 93 | 111 | mqueue_destroy_resource(sipc_key); |
|---|
| … | … | |
| 97 | 115 | shm_destroy_resource(sipc_key); |
|---|
| 98 | 116 | break; |
|---|
| 99 | | default: |
|---|
| 100 | | return; |
|---|
| 101 | | } |
|---|
| 102 | | |
|---|
| 103 | | } |
|---|
| 104 | | |
|---|
| 105 | | int sipc_create(char *key, int ipc_type) |
|---|
| 106 | | { |
|---|
| 107 | | key_t sipc_key; |
|---|
| 108 | | |
|---|
| 109 | | sipc_key = ftok(key, 'a'); |
|---|
| 110 | | if ((int)sipc_key < 0) { |
|---|
| 111 | | fprintf(stderr, "ftok: %s\n", strerror(errno)); |
|---|
| 112 | | return -1; |
|---|
| 113 | 117 | } |
|---|
| 114 | | |
|---|
| 115 | | if (ipc_type >= SIPC_NUM_TYPES || ipc_type < 0) |
|---|
| 116 | | return -1; |
|---|
| 117 | | |
|---|
| 118 | | /* Choose which type of IPC resource we create */ |
|---|
| 119 | | switch (ipc_type) { |
|---|
| 120 | | case SIPC_SYSV_MQUEUES: |
|---|
| 121 | | case SIPC_SYSV_SHM: |
|---|
| 122 | | return mqueue_create(sipc_key); |
|---|
| 123 | | default: |
|---|
| 124 | | return -1; |
|---|
| 125 | | } |
|---|
| 126 | | } |
|---|
| 127 | | |
|---|
| 128 | | int sipc_connect(sipc_t *sipc) |
|---|
| 129 | | { |
|---|
| 130 | | if (!sipc) |
|---|
| 131 | | return -1; |
|---|
| 132 | | |
|---|
| 133 | | return sipc->funcs->sipc_connect(sipc); |
|---|
| 134 | | } |
|---|
| 135 | | |
|---|
| 136 | | void sipc_disconnect(sipc_t *sipc) |
|---|
| 137 | | { |
|---|
| 138 | | if (!sipc) |
|---|
| 139 | | return; |
|---|
| 140 | | |
|---|
| 141 | | sipc->funcs->sipc_disconnect(sipc); |
|---|
| 142 | 118 | } |
|---|
| 143 | 119 | |
|---|
| … | … | |
| 154 | 130 | if (!sipc) |
|---|
| 155 | 131 | return -1; |
|---|
| 156 | | |
|---|
| | 132 | |
|---|
| 157 | 133 | return sipc->funcs->sipc_send_data(sipc, msg_len); |
|---|
| 158 | 134 | } |
|---|
| … | … | |
| 167 | 143 | |
|---|
| 168 | 144 | void sipc_error(sipc_t *sipc, const char *fmt, ...) |
|---|
| 169 | | { |
|---|
| | 145 | { |
|---|
| 170 | 146 | if (!sipc) |
|---|
| 171 | 147 | return; |
|---|
| r4 |
r16 |
|
| 38 | 38 | |
|---|
| 39 | 39 | /* Creation functions */ |
|---|
| | 40 | int sipc_mqueue_create(sipc_t *sipc); |
|---|
| | 41 | int sipc_shm_create(sipc_t *sipc); |
|---|
| 40 | 42 | int mqueue_create(key_t key); |
|---|
| | 43 | |
|---|
| | 44 | /* Attach functions */ |
|---|
| | 45 | int sipc_mqueue_attach(sipc_t *sipc); |
|---|
| | 46 | int sipc_shm_attach(sipc_t *sipc); |
|---|
| | 47 | |
|---|
| | 48 | /* Detach functions */ |
|---|
| | 49 | void sipc_mqueue_detach(sipc_t *sipc); |
|---|
| | 50 | void sipc_shm_detach(sipc_t *sipc); |
|---|
| 41 | 51 | |
|---|
| 42 | 52 | /* Destruction functions */ |
|---|
| … | … | |
| 50 | 60 | /* all ipc backends must implement all of these functions */ |
|---|
| 51 | 61 | struct sipc_func_table { |
|---|
| 52 | | int (*sipc_connect) (sipc_t *sipc); |
|---|
| 53 | | void (*sipc_disconnect) (sipc_t *sipc); |
|---|
| | 62 | int (*sipc_create) (sipc_t *sipc); |
|---|
| | 63 | int (*sipc_attach) (sipc_t *sipc); |
|---|
| 54 | 64 | char *(*sipc_get_data_ptr) (sipc_t *sipc); |
|---|
| 55 | 65 | int (*sipc_send_data) (sipc_t *sipc, int msg_len); |
|---|
| 56 | 66 | int (*sipc_recv_data) (sipc_t *sipc, char **data, int *len); |
|---|
| 57 | | void (*sipc_destroy_handle) (sipc_t *sipc); |
|---|
| | 67 | void (*sipc_detach) (sipc_t *sipc); |
|---|
| 58 | 68 | void (*_sipc_error) (const char *fmt, va_list ap); |
|---|
| 59 | 69 | }; |
|---|
| … | … | |
| 62 | 72 | key_t key; |
|---|
| 63 | 73 | int ipc_type; |
|---|
| 64 | | int sender; |
|---|
| | 74 | int role; |
|---|
| 65 | 75 | union { |
|---|
| 66 | 76 | int fd; /* file desciptor for socket connections */ |
|---|
| r8 |
r16 |
|
| 40 | 40 | |
|---|
| 41 | 41 | static struct sipc_func_table mqueue_funcs = { |
|---|
| 42 | | .sipc_connect = sipc_mqueue_connect, |
|---|
| 43 | | .sipc_disconnect = sipc_mqueue_disconnect, |
|---|
| | 42 | .sipc_create = sipc_mqueue_create, |
|---|
| | 43 | .sipc_attach = sipc_mqueue_attach, |
|---|
| 44 | 44 | .sipc_get_data_ptr = sipc_mqueue_get_data_ptr, |
|---|
| 45 | 45 | .sipc_send_data = sipc_mqueue_send_data, |
|---|
| 46 | 46 | .sipc_recv_data = sipc_mqueue_recv_data, |
|---|
| 47 | | .sipc_destroy_handle = sipc_mqueue_destroy_handle, |
|---|
| | 47 | .sipc_detach = sipc_mqueue_detach, |
|---|
| 48 | 48 | ._sipc_error = sipc_mqueue_error, |
|---|
| 49 | 49 | }; |
|---|
| … | … | |
| 66 | 66 | |
|---|
| 67 | 67 | sipc->funcs = &mqueue_funcs; |
|---|
| | 68 | sipc->data = NULL; |
|---|
| 68 | 69 | |
|---|
| 69 | 70 | /* Determine maximum size of a message from proc */ |
|---|
| 70 | 71 | SIPC_MQUEUE_MSG_SZ = get_max_msg(sipc); |
|---|
| 71 | | if (SIPC_MQUEUE_MSG_SZ < 0) { |
|---|
| 72 | | free(sipc->data); |
|---|
| 73 | | return -1; |
|---|
| 74 | | } |
|---|
| 75 | | |
|---|
| | 72 | if (SIPC_MQUEUE_MSG_SZ < 0) |
|---|
| | 73 | return -1; |
|---|
| | 74 | |
|---|
| | 75 | return 0; |
|---|
| | 76 | } |
|---|
| | 77 | |
|---|
| | 78 | /* Create a message queue having the specified key. |
|---|
| | 79 | * This function should only be called by a helper application |
|---|
| | 80 | * and not by the sender or reciever. */ |
|---|
| | 81 | int sipc_mqueue_create(sipc_t *sipc) |
|---|
| | 82 | { |
|---|
| | 83 | int msqid; |
|---|
| | 84 | |
|---|
| | 85 | msqid = mqueue_create(sipc->key); |
|---|
| | 86 | if (msqid < 0) { |
|---|
| | 87 | fprintf(stderr, "msgget: %s\n", strerror(errno)); |
|---|
| | 88 | return -1; |
|---|
| | 89 | } |
|---|
| | 90 | |
|---|
| | 91 | sipc->msqid = msqid; |
|---|
| | 92 | return 0; |
|---|
| | 93 | } |
|---|
| | 94 | |
|---|
| | 95 | void sipc_mqueue_detach(sipc_t *sipc) |
|---|
| | 96 | { |
|---|
| | 97 | free(sipc->data); |
|---|
| | 98 | sipc->data = NULL; |
|---|
| | 99 | } |
|---|
| | 100 | |
|---|
| | 101 | /* Attach to an existing message queue. */ |
|---|
| | 102 | int sipc_mqueue_attach(sipc_t *sipc) |
|---|
| | 103 | { |
|---|
| 76 | 104 | /* Allocate data member */ |
|---|
| 77 | | sipc->data = NULL; |
|---|
| 78 | 105 | sipc->data = calloc(1, sipc->len); |
|---|
| 79 | 106 | if (!sipc->data) { |
|---|
| … | … | |
| 81 | 108 | return -1; |
|---|
| 82 | 109 | } |
|---|
| 83 | | |
|---|
| 84 | | return 0; |
|---|
| 85 | | } |
|---|
| 86 | | |
|---|
| 87 | | void sipc_mqueue_destroy_handle(sipc_t *sipc) |
|---|
| 88 | | { |
|---|
| 89 | | free(sipc->data); |
|---|
| 90 | | } |
|---|
| 91 | | |
|---|
| 92 | | /* Create a message queue, or connect to an existing |
|---|
| 93 | | * message queue. */ |
|---|
| 94 | | int sipc_mqueue_connect(sipc_t *sipc) |
|---|
| 95 | | { |
|---|
| 96 | | sipc->msqid = mqueue_connect(sipc->key, sipc->sender); |
|---|
| | 110 | |
|---|
| | 111 | sipc->msqid = mqueue_connect(sipc->key, sipc->role); |
|---|
| 97 | 112 | if (sipc->msqid < 0) { |
|---|
| 98 | 113 | sipc_error(sipc, "msgget: %s\n", strerror(errno)); |
|---|
| 99 | | return -1; |
|---|
| 100 | | } |
|---|
| 101 | | |
|---|
| 102 | | return 0; |
|---|
| 103 | | } |
|---|
| 104 | | |
|---|
| 105 | | /* Do nothing here; disconnecting from the |
|---|
| 106 | | * message queue is done by a disconnector process */ |
|---|
| 107 | | void sipc_mqueue_disconnect(sipc_t *sipc) |
|---|
| 108 | | { |
|---|
| | 114 | free(sipc->data); |
|---|
| | 115 | sipc->data = NULL; |
|---|
| | 116 | return -1; |
|---|
| | 117 | } |
|---|
| | 118 | |
|---|
| | 119 | return 0; |
|---|
| 109 | 120 | } |
|---|
| 110 | 121 | |
|---|
| … | … | |
| 123 | 134 | struct msgbuf *mbuf = NULL; |
|---|
| 124 | 135 | |
|---|
| 125 | | if (!sipc->sender) |
|---|
| | 136 | if (sipc->role != SIPC_SENDER) |
|---|
| 126 | 137 | goto err; |
|---|
| 127 | 138 | |
|---|
| … | … | |
| 177 | 188 | if (!data) |
|---|
| 178 | 189 | goto err; |
|---|
| 179 | | if (sipc->sender) { |
|---|
| 180 | | sipc_error(sipc, "sipc_send_data called with sender flag enabled in IPC structure\n"); |
|---|
| | 190 | if (sipc->role != SIPC_RECEIVER) { |
|---|
| | 191 | sipc_error(sipc, "sipc_send_data called without receiver flag enabled in IPC structure\n"); |
|---|
| 181 | 192 | goto err; |
|---|
| 182 | 193 | } |
|---|
| r11 |
r16 |
|
| 37 | 37 | |
|---|
| 38 | 38 | #define SHM_RPERMS S_IRUSR|S_IRGRP|S_IROTH |
|---|
| 39 | | #define SHM_SPERMS SHM_RPERMS|S_IWUSR|S_IWGRP|S_IWOTH|IPC_CREAT|IPC_EXCL |
|---|
| | 39 | #define SHM_SPERMS SHM_RPERMS|S_IWUSR|S_IWGRP|S_IWOTH |
|---|
| | 40 | #define SHM_CPERMS SHM_RPERMS|SHM_SPERMS|IPC_CREAT|IPC_EXCL |
|---|
| 40 | 41 | |
|---|
| 41 | 42 | static struct sipc_func_table shm_funcs = { |
|---|
| 42 | | .sipc_connect = sipc_shm_connect, |
|---|
| 43 | | .sipc_disconnect = sipc_shm_disconnect, |
|---|
| | 43 | .sipc_create = sipc_shm_create, |
|---|
| | 44 | .sipc_attach = sipc_shm_attach, |
|---|
| 44 | 45 | .sipc_get_data_ptr = sipc_shm_get_data_ptr, |
|---|
| 45 | 46 | .sipc_send_data = sipc_shm_send_data, |
|---|
| 46 | 47 | .sipc_recv_data = sipc_shm_recv_data, |
|---|
| 47 | | .sipc_destroy_handle = sipc_shm_destroy_handle, |
|---|
| | 48 | .sipc_detach = sipc_shm_detach, |
|---|
| 48 | 49 | ._sipc_error = sipc_shm_error |
|---|
| 49 | 50 | }; |
|---|
| … | … | |
| 60 | 61 | } |
|---|
| 61 | 62 | |
|---|
| 62 | | /* Do nothing here; destroying the shm segment is done |
|---|
| 63 | | * by a destructor process. */ |
|---|
| 64 | | /* Processes should detach from shared memory in sipc_shm_disconnect */ |
|---|
| 65 | | void sipc_shm_destroy_handle(sipc_t *sipc) |
|---|
| 66 | | { |
|---|
| 67 | | } |
|---|
| 68 | | |
|---|
| 69 | | /* We already have attached to shm segment, so here we connect side channel */ |
|---|
| 70 | | int sipc_shm_connect(sipc_t *sipc) |
|---|
| | 63 | int sipc_shm_create(sipc_t *sipc) |
|---|
| | 64 | { |
|---|
| | 65 | if (!sipc) |
|---|
| | 66 | goto err; |
|---|
| | 67 | |
|---|
| | 68 | /* Create the shm segment */ |
|---|
| | 69 | sipc->s.shmid = shmget(sipc->key, sipc->len, SHM_CPERMS); |
|---|
| | 70 | if (sipc->s.shmid < 0) { |
|---|
| | 71 | sipc_error(sipc, "shmget: %s\n", strerror(errno)); |
|---|
| | 72 | goto err; |
|---|
| | 73 | } |
|---|
| | 74 | |
|---|
| | 75 | /* Create the side channel */ |
|---|
| | 76 | sipc->s.msqid = mqueue_create(sipc->key); |
|---|
| | 77 | if (sipc->s.shmid < 0) |
|---|
| | 78 | goto err; |
|---|
| | 79 | |
|---|
| | 80 | /* Set capacity of side channel to 1 message */ |
|---|
| | 81 | if (sipc->role == SIPC_SENDER && |
|---|
| | 82 | mqueue_set_capacity(sipc->s.msqid, sizeof(struct msgbuf)) < 0) |
|---|
| | 83 | goto err; |
|---|
| | 84 | |
|---|
| | 85 | return 0; |
|---|
| | 86 | |
|---|
| | 87 | err: |
|---|
| | 88 | if (sipc->s.shmid != (key_t)-1) |
|---|
| | 89 | shmctl(sipc->s.shmid, IPC_RMID, NULL); |
|---|
| | 90 | return -1; |
|---|
| | 91 | } |
|---|
| | 92 | |
|---|
| | 93 | int sipc_shm_attach(sipc_t *sipc) |
|---|
| 71 | 94 | { |
|---|
| 72 | 95 | int flags = 0; |
|---|
| … | … | |
| 75 | 98 | goto err; |
|---|
| 76 | 99 | |
|---|
| 77 | | /* Create the shm segment */ |
|---|
| 78 | | flags = sipc->sender ? SHM_SPERMS : SHM_RPERMS; |
|---|
| | 100 | /* Get the (existing) shm segment */ |
|---|
| | 101 | flags = sipc->role == SIPC_SENDER ? SHM_SPERMS : SHM_RPERMS; |
|---|
| 79 | 102 | sipc->s.shmid = shmget(sipc->key, sipc->len, flags); |
|---|
| 80 | 103 | if (sipc->s.shmid < 0) { |
|---|
| … | … | |
| 84 | 107 | |
|---|
| 85 | 108 | /* Attach to the shm segment */ |
|---|
| 86 | | flags = sipc->sender ? 0 : SHM_RDONLY; |
|---|
| | 109 | flags = sipc->role == SIPC_SENDER ? 0 : SHM_RDONLY; |
|---|
| 87 | 110 | if ((sipc->data = shmat(sipc->s.shmid, NULL, flags)) == (char *)-1) { |
|---|
| 88 | 111 | sipc_error(sipc, "shmat: %s\n", strerror(errno)); |
|---|
| … | … | |
| 91 | 114 | |
|---|
| 92 | 115 | /* Connect side channel */ |
|---|
| 93 | | sipc->s.msqid = mqueue_connect(sipc->key, sipc->sender); |
|---|
| | 116 | sipc->s.msqid = mqueue_connect(sipc->key, sipc->role); |
|---|
| 94 | 117 | if (sipc->s.msqid < 0) { |
|---|
| 95 | 118 | sipc_error(sipc, "%s\n", "Unable to connect message queue"); |
|---|
| … | … | |
| 97 | 120 | } |
|---|
| 98 | 121 | |
|---|
| 99 | | /* Set capacity of side channel to 1 message */ |
|---|
| 100 | | if (sipc->sender && mqueue_set_capacity(sipc->s.msqid, sizeof(struct msgbuf)) < 0) |
|---|
| 101 | | goto err; |
|---|
| 102 | | |
|---|
| 103 | 122 | return 0; |
|---|
| 104 | 123 | err: |
|---|
| 105 | | sipc_disconnect(sipc); |
|---|
| | 124 | sipc_shm_detach(sipc); |
|---|
| 106 | 125 | return -1; |
|---|
| 107 | 126 | } |
|---|
| 108 | 127 | |
|---|
| 109 | | void sipc_shm_disconnect(sipc_t *sipc) |
|---|
| | 128 | void sipc_shm_detach(sipc_t *sipc) |
|---|
| 110 | 129 | { |
|---|
| 111 | 130 | if (!sipc) |
|---|
| … | … | |
| 113 | 132 | |
|---|
| 114 | 133 | /* If we're the receiver, disconnect side channel */ |
|---|
| 115 | | if (!sipc->sender) |
|---|
| | 134 | if (sipc->role == SIPC_RECEIVER) |
|---|
| 116 | 135 | mqueue_disconnect(sipc->s.msqid); |
|---|
| 117 | 136 | |
|---|
| … | … | |
| 121 | 140 | sipc_error(sipc, "shmdt: %s\n", strerror(errno)); |
|---|
| 122 | 141 | } |
|---|
| 123 | | |
|---|
| 124 | 142 | } |
|---|
| 125 | 143 | |
|---|
Download in other formats:
* Generating other formats may take time.