summaryrefslogtreecommitdiffstats
path: root/examples/shm/shm.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/shm/shm.c')
-rw-r--r--examples/shm/shm.c178
1 files changed, 178 insertions, 0 deletions
diff --git a/examples/shm/shm.c b/examples/shm/shm.c
new file mode 100644
index 0000000..2469115
--- /dev/null
+++ b/examples/shm/shm.c
@@ -0,0 +1,178 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <aes.h>
+
+sem_t *enc_sem, *get_sem;
+
+#define SHM_SIZE 64*1024
+
+void child(pid_t parent, void* mem)
+{
+ char key[16];
+ char iv[16];
+ struct crypto_aes_ctx ctx;
+ uint32_t mem_size;
+
+ for (;;) {
+ memset(key, 0xa3, sizeof(key));
+ memset(iv, 0x3, sizeof(iv));
+
+ sem_wait(enc_sem);
+
+ crypto_aes_expand_key(&ctx, (void*)key, sizeof(key));
+
+ memcpy(&mem_size, mem, sizeof(mem_size));
+
+ crypto_cbc_encrypt(&ctx, mem, mem_size, mem, iv);
+
+ sem_post(get_sem);
+ }
+}
+
+static int must_finish = 0;
+
+static void alarm_handler(int signo)
+{
+ must_finish = 1;
+}
+
+static double udifftimeval(struct timeval start, struct timeval end)
+{
+ return (double)(end.tv_usec - start.tv_usec) +
+ (double)(end.tv_sec - start.tv_sec) * 1000 * 1000;
+}
+
+static void value2human(double bytes, double time, double* data, double* speed,char* metric)
+{
+ if (bytes > 1000 && bytes < 1000*1000) {
+ *data = ((double)bytes)/1000;
+ *speed = *data/time;
+ strcpy(metric, "Kb");
+ return;
+ } else if (bytes >= 1000*1000 && bytes < 1000*1000*1000) {
+ *data = ((double)bytes)/(1000*1000);
+ *speed = *data/time;
+ strcpy(metric, "Mb");
+ return;
+ } else if (bytes >= 1000*1000*1000) {
+ *data = ((double)bytes)/(1000*1000*1000);
+ *speed = *data/time;
+ strcpy(metric, "Gb");
+ return;
+ } else {
+ *data = (double)bytes;
+ *speed = *data/time;
+ strcpy(metric, "bytes");
+ return;
+ }
+}
+
+void parent(pid_t child, void* mem)
+{
+struct timeval start, end;
+uint32_t chunksize;
+double total = 0;
+double secs, ddata, dspeed;
+char metric[16];
+
+ signal(SIGALRM, alarm_handler);
+
+ /* set a default value in shared memory */
+
+ for (chunksize = 256; chunksize <= (64 * 1024); chunksize *= 2) {
+ memset(mem, 0x33, chunksize);
+
+ printf("\tEncrypting in chunks of %d bytes: ", chunksize);
+ fflush(stdout);
+
+ total = 0;
+ must_finish = 0;
+ alarm(5);
+ gettimeofday(&start, NULL);
+
+ do {
+ memcpy(mem, &chunksize, sizeof(chunksize));
+
+ sem_post(enc_sem);
+
+ sem_wait(get_sem);
+ total+=chunksize;
+ } while(must_finish == 0);
+
+ gettimeofday(&end, NULL);
+
+ secs = udifftimeval(start, end)/ 1000000.0;
+ value2human(total, secs, &ddata, &dspeed, metric);
+ printf ("done. %.2f %s in %.2f secs: ", ddata, metric, secs);
+ printf ("%.2f %s/sec\n", dspeed, metric);
+ }
+
+}
+
+int main()
+{
+ int shmid, shmid2;
+ char c, *shm, *s, *semmem;
+ pid_t pid;
+
+ signal(SIGUSR1, SIG_IGN);
+ signal(SIGUSR2, SIG_IGN);
+
+ if ((shmid = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0660)) < 0) {
+ perror("shmget fail");
+ return 1;
+ }
+
+ if ((shm = (char *) shmat(shmid, 0, 0)) == (char *) -1) {
+ perror("shmat : parent");
+ return 2;
+ }
+
+ if ((shmid2 = shmget(IPC_PRIVATE, 2*sizeof(sem_t), IPC_CREAT | 0660)) < 0) {
+ perror("shmget fail");
+ return 1;
+ }
+
+ if ((semmem = (char *) shmat(shmid2, 0, 0)) == (char *) -1) {
+ perror("shmat : parent");
+ return 2;
+ }
+
+ enc_sem = (void*)semmem;
+ get_sem = (void*)semmem + sizeof(sem_t);
+
+ sem_init(enc_sem, 1, 0);
+ sem_init(get_sem, 1, 0);
+
+ printf("Addresses in parent\n");
+ printf("shared mem: %p\n", shm);
+
+ s = shm; // s now references shared mem
+ for (c = 'A'; c <= 'Z'; ++c) // put some info there
+ *s++ = c;
+ *s = '\0'; // terminate the sequence
+
+ switch (pid=fork()) {
+ case -1:
+ perror("fork");
+ return 3;
+ default:
+ parent(pid, shm);
+ kill(pid, SIGTERM);
+ wait(0); // let the child finish
+ shmdt(shm);
+ shmctl(shmid, IPC_RMID, (struct shmid_ds *) 0);
+ break;
+ case 0:
+ child(getppid(), shm);
+ shmdt(shm);
+ break;
+ }
+ return 0;
+}