support little-endian bitmaps
[tridge/junkcode.git] / shm_sample.c
1 #include <stdlib.h>
2 #include <unistd.h>
3 #include <stdio.h>
4 #include <string.h>
5
6 #if USE_SHM
7 #include <sys/ipc.h>
8 #include <sys/shm.h>
9
10 /* return a pointer to a anonymous shared memory segment of size "size"
11    which will persist across fork() but will disappear when all processes
12    exit 
13
14    The memory is not zeroed 
15
16    This function uses system5 shared memory. It takes advantage of a property
17    that the memory is not destroyed if it is attached when the id is removed
18    */
19 void *shm_setup(int size)
20 {
21         int shmid;
22         void *ret;
23
24         shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
25         if (shmid == -1) {
26                 printf("can't get shared memory\n");
27                 exit(1);
28         }
29         ret = (void *)shmat(shmid, 0, 0);
30         if (!ret || ret == (void *)-1) {
31                 printf("can't attach to shared memory\n");
32                 return NULL;
33         }
34         /* the following releases the ipc, but note that this process
35            and all its children will still have access to the memory, its
36            just that the shmid is no longer valid for other shm calls. This
37            means we don't leave behind lots of shm segments after we exit 
38
39            See Stevens "advanced programming in unix env" for details
40            */
41         shmctl(shmid, IPC_RMID, 0);
42
43
44         
45         return ret;
46 }
47 #endif
48
49
50
51 #if USE_DEVZERO
52 #include <sys/mman.h>
53 #include <fcntl.h>
54
55 /* return a pointer to a /dev/zero shared memory segment of size "size"
56    which will persist across fork() but will disappear when all processes
57    exit 
58
59    The memory is zeroed automatically
60
61    This relies on /dev/zero being shared mmap capable, which it is
62    only under some OSes (Linux 2.1 _not_ included)
63  */
64 void *shm_setup(int size)
65 {
66         void *ret;
67         int fd;
68
69         fd = open("/dev/zero", O_RDWR);
70         if (fd == -1) {
71                 return NULL;
72         }
73         ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FILE,
74                    fd, 0);
75
76         /* note that we don't need to keep the file open */
77         close(fd);
78         if (ret == (void *)-1) return NULL;
79         return ret;
80 }
81 #endif
82
83
84 #if USE_MAPANON
85 #include <sys/mman.h>
86
87 /* return a pointer to a /dev/zero shared memory segment of size "size"
88    which will persist across fork() but will disappear when all processes
89    exit 
90
91    The memory is zeroed automatically
92
93    This relies on anonyous shared mmap, which only some OSes can
94    do. Linux 2.1 is _not_ one of them.
95    */
96 void *shm_setup(int size)
97 {
98         void *ret;
99         ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED,
100                    -1, 0);
101         if (ret == (void *)-1) return NULL;
102         return ret;
103 }
104 #endif
105
106
107 #if USE_MAPFILE
108 #include <sys/mman.h>
109 #include <fcntl.h>
110
111 /* return a pointer to a /dev/zero shared memory segment of size "size"
112    which will persist across fork() but will disappear when all processes
113    exit 
114
115    The memory is zeroed automatically
116
117    This relies only on shared mmap, which almost any mmap capable OS
118    can do. Linux can do this as of version 1.2 (I believe). certainly
119    all recent versions can do it.
120   */
121 void *shm_setup(int size)
122 {
123         void *ret;
124         int fd, zero=0;
125         char template[20] = "/tmp/shm.XXXXXX";
126
127         /* mkstemp() isn't really portable but use it if it exists as
128            otherwise you are open to some nasty soft-link /tmp based
129            hacks */
130         fd = mkstemp(template);
131         if (fd == -1) {
132                 return NULL;
133         }
134         lseek(fd, size, SEEK_SET);
135         write(fd, &zero, sizeof(zero));
136         ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED,
137                    fd, 0);
138         close(fd);
139         unlink(template);
140         if (ret == (void *)-1) return NULL;
141         return ret;
142 }
143 #endif
144
145
146 int main(int argc, char *argv[])
147 {
148         volatile char *buf;
149         int size;
150         pid_t child, parent;
151
152         if (argc < 2) {
153                 printf("shm_sample <size>\n");
154                 exit(1);
155         }
156
157         size = atoi(argv[1]);
158
159         buf = shm_setup(size);
160
161         if (!buf) {
162                 printf("shm_setup(%d) failed\n", size);
163                 exit(1);
164         }
165         memset(buf, 0, sizeof(int));
166
167         parent = getpid();
168         child = fork();
169
170         if (!child) {
171                 *(int *)buf = parent;
172                 return 0;
173         }
174
175         waitpid(child, 0, 0);
176
177         if (*(int *)buf == 0) {
178                 printf("memory not shared?\n");
179         } else {
180                 printf("pid via shm is %d real pid is %d\n",
181                        *(int *)buf, parent);
182         }
183
184         return 0;
185 }
186