#include #include #include int main () { int segment_id; char* shared_memory; struct shmid_ds shmbuffer; int segment_size; const int shared_segment_size = 0x6400; /* Allocate a shared memory segment. */ segment_id = shmget (IPC_PRIVATE, shared_segment_size, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); /* Attach the shared memory segment. */ shared_memory = (char*) shmat (segment_id, 0, 0); printf (“shared memory attached at address %p/n”, shared_memory); /* Determine the segment’s size. */ shmctl (segment_id, IPC_STAT, &shmbuffer); segment_size = shmbuffer.shm_segsz; printf (“segment size: %d/n”, segment_size); /* Write a string to the shared memory segment. */ sprintf (shared_memory, “Hello, world.”); /* Detach the shared memory segment. */ shmdt (shared_memory); /* Reattach the shared memory segment, at a different address. */ shared_memory = (char*) shmat (segment_id, (void*) 0x5000000, 0); printf (“shared memory reattached at address %p/n”, shared_memory); /* Print out the string from shared memory. */ printf (“%s/n”, shared_memory); /* Detach the shared memory segment. */ shmdt (shared_memory); /* Deallocate the shared memory segment. */ shmctl (segment_id, IPC_RMID, 0); return 0; }
ipcs命令可用查看进程间通信机制的信息 使用-m可查看共享内存的信息 % ipcs -m ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 1627649 user 640 25600 0 ipcrm命令可删除进程间通信对象. % ipcrm shm 1627649 [liuchao@localhost ~]$ ipcs ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 196608 liuchao 600 393216 2 dest 0x764867bd 65537 liuchao 600 1 0 0x2c0056d5 98306 liuchao 600 1 0 0x500e7827 131075 liuchao 600 1 0 0x20e0f21d 163844 liuchao 600 1 0 0x00000000 229381 liuchao 600 393216 2 dest 0x00000000 262150 liuchao 600 393216 2 dest 0x00000000 294919 liuchao 600 393216 2 dest 0x00000000 327688 liuchao 600 393216 2 dest 0x00000000 360457 liuchao 600 393216 2 dest 0x00000000 393226 liuchao 600 393216 2 dest 0x00000000 425995 liuchao 600 393216 2 dest 0x00000000 458764 liuchao 600 393216 2 dest 0x00000000 491533 liuchao 600 393216 2 dest 0x00000000 557070 liuchao 600 393216 2 dest 0x00000000 589839 liuchao 600 393216 2 dest ------ Semaphore Arrays -------- key semid owner perms nsems 0x59d9bc4a 0 liuchao 600 1 0x3bd464f2 32769 liuchao 600 1 ------ Message Queues -------- key msqid owner perms used-bytes messages |
#include #include #include /* We must define union semun ourselves. */ union semun { int val; struct semid_ds *buf; unsigned short int *array; struct seminfo *__buf; }; /* Obtain a binary semaphore’s ID, allocating if necessary. */ int binary_semaphore_allocation (key_t key, int sem_flags) { return semget (key, 1, sem_flags); } /* Deallocate a binary semaphore. All users must have finished their use. Returns -1 on failure. */ int binary_semaphore_deallocate (int semid) { union semun ignored_argument; return semctl (semid, 1, IPC_RMID, ignored_argument); } |
#include #include #include /* We must define union semun ourselves. */ union semun { int val; struct semid_ds *buf; unsigned short int *array; struct seminfo *__buf; }; /* Initialize a binary semaphore with a value of 1. */ int binary_semaphore_initialize (int semid) { union semun argument; unsigned short values[1]; values[0] = 1; argument.array = values; return semctl (semid, 0, SETALL, argument); } |
#include #include #include /* Wait on a binary semaphore. Block until the semaphore value is positive, then decrement it by 1. */ int binary_semaphore_wait (int semid) { struct sembuf operations[1]; /* Use the first (and only) semaphore. */ operations[0].sem_num = 0; /* Decrement by 1. */ operations[0].sem_op = -1; /* Permit undo’ing. */ operations[0].sem_flg = SEM_UNDO; return semop (semid, operations, 1); } /* Post to a binary semaphore: increment its value by 1. This returns immediately. */ int binary_semaphore_post (int semid) { struct sembuf operations[1]; /* Use the first (and only) semaphore. */ operations[0].sem_num = 0; /* Increment by 1. */ operations[0].sem_op = 1; /* Permit undo’ing. */ operations[0].sem_flg = SEM_UNDO; return semop (semid, operations, 1); } |
(mmap-write.c) Write a Random Number to a Memory-Mapped File #include #include #include #include #include #include #include #define FILE_LENGTH 0x100 /* Return a uniformly random number in the range [low,high]. */ int random_range (unsigned const low, unsigned const high) { unsigned const range = high - low + 1; return low + (int) (((double) range) * rand () / (RAND_MAX + 1.0)); } int main (int argc, char* const argv[]) { int fd; void* file_memory; /* Seed the random number generator. */ srand (time (NULL)); /* Prepare a file large enough to hold an unsigned integer. */ fd = open (argv[1], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); lseek (fd, FILE_LENGTH+1, SEEK_SET); write (fd, “”, 1); lseek (fd, 0, SEEK_SET); /* Create the memory mapping. */ file_memory = mmap (0, FILE_LENGTH, PROT_WRITE, MAP_SHARED, fd, 0); close (fd); /* Write a random integer to memory-mapped area. */ sprintf((char*) file_memory, “%d/n”, random_range (-100, 100)); /* Release the memory (unnecessary because the program exits). */ munmap (file_memory, FILE_LENGTH); return 0; } (mmap-read.c) Read an Integer from a Memory-Mapped File, and Double It #include #include #include #include #include #include #define FILE_LENGTH 0x100 int main (int argc, char* const argv[]) { int fd; void* file_memory; int integer; /* Open the file. */ fd = open (argv[1], O_RDWR, S_IRUSR | S_IWUSR); /* Create the memory mapping. */ file_memory = mmap (0, FILE_LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); close (fd); /* Read the integer, print it out, and double it. */ sscanf (file_memory, “%d”, &integer); printf (“value: %d/n”, integer); sprintf ((char*) file_memory, “%d/n”, 2 * integer); /* Release the memory (unnecessary because the program exits). */ munmap (file_memory, FILE_LENGTH); return 0; } |
msync (mem_addr, mem_length, MS_SYNC | MS_INVALIDATE);
int pipe_fds[2]; int read_fd; int write_fd; pipe (pipe_fds); read_fd = pipe_fds[0]; write_fd = pipe_fds[1]; |
#include #include #include /* Write COUNT copies of MESSAGE to STREAM, pausing for a second between each. */ void writer (const char* message, int count, FILE* stream) { for (; count > 0; --count) { /* Write the message to the stream, and send it off immediately. */ fprintf (stream, “%s/n”, message); fflush (stream); /* Snooze a while. */ sleep (1); } } /* Read random strings from the stream as long as possible. */ void reader (FILE* stream) { char buffer[1024]; /* Read until we hit the end of the stream. fgets reads until either a newline or the end-of-file. */ while (!feof (stream) && !ferror (stream) && fgets (buffer, sizeof (buffer), stream) != NULL) fputs (buffer, stdout); } int main () { int fds[2]; pid_t pid; /* Create a pipe. File descriptors for the two ends of the pipe are placed in fds. */ pipe (fds); /* Fork a child process. */ pid = fork (); if (pid == (pid_t) 0) { FILE* stream; /* This is the child process. Close our copy of the write end of the file descriptor. */ close (fds[1]); /* Convert the read file descriptor to a FILE object, and read from it. */ stream = fdopen (fds[0], “r”); reader (stream); close (fds[0]); } else { /* This is the parent process. */ FILE* stream; /* Close our copy of the read end of the file descriptor. */ close (fds[0]); /* Convert the write file descriptor to a FILE object, and write to it. */ stream = fdopen (fds[1], “w”); writer (“Hello, world.”, 5, stream); close (fds[1]); } return 0; } |
#include #include #include #include int main () { int fds[2]; pid_t pid; /* Create a pipe. File descriptors for the two ends of the pipe are placed in fds. */ pipe (fds); /* Fork a child process. */ pid = fork (); if (pid == (pid_t) 0) { /* This is the child process. Close our copy of the write end of the file descriptor. */ close (fds[1]); /* Connect the read end of the pipe to standard input. */ dup2 (fds[0], STDIN_FILENO); /* Replace the child process with the “sort” program. */ execlp (“sort”, “sort”, 0); } else { /* This is the parent process. */ FILE* stream; /* Close our copy of the read end of the file descriptor. */ close (fds[0]); /* Convert the write file descriptor to a FILE object, and write to it. */ stream = fdopen (fds[1], “w”); fprintf (stream, “This is a test./n”); fprintf (stream, “Hello, world./n”); fprintf (stream, “My dog has fleas./n”); fprintf (stream, “This program is great./n”); fprintf (stream, “One fish, two fish./n”); fflush (stream); close (fds[1]); /* Wait for the child process to finish. */ waitpid (pid, NULL, 0); } return 0; } |
#include #include int main () { FILE* stream = popen (“sort”, “w”); fprintf (stream, “This is a test./n”); fprintf (stream, “Hello, world./n”); fprintf (stream, “My dog has fleas./n”); fprintf (stream, “This program is great./n”); fprintf (stream, “One fish, two fish./n”); return pclose (stream); } |
% mkfifo /tmp/fifo % ls -l /tmp/fifo prw-rw-rw- 1 samuel users 0 Jan 16 14:04 /tmp/fifo |
访问同一台机器的套接字可以使用本地命名空间:PF_LOCAL和PF_UNIX
(socket-server.c) Local Namespace Socket Server #include #include #include #include #include #include /* Read text from the socket and print it out. Continue until the socket closes. Return nonzero if the client sent a “quit” message, zero otherwise. */ int server (int client_socket) { while (1) { int length; char* text; /* First, read the length of the text message from the socket. If read returns zero, the client closed the connection. */ if (read (client_socket, &length, sizeof (length)) == 0) return 0; /* Allocate a buffer to hold the text. */ text = (char*) malloc (length); /* Read the text itself, and print it. */ read (client_socket, text, length); printf (“%s/n”, text); /* Free the buffer. */ free (text); /* If the client sent the message “quit,” we’re all done. */ if (!strcmp (text, “quit”)) return 1; } } int main (int argc, char* const argv[]) { const char* const socket_name = argv[1]; int socket_fd; struct sockaddr_un name; int client_sent_quit_message; /* Create the socket. */ socket_fd = socket (PF_LOCAL, SOCK_STREAM, 0); /* Indicate that this is a server. */ name.sun_family = AF_LOCAL; strcpy (name.sun_path, socket_name); bind (socket_fd, &name, SUN_LEN (&name)); /* Listen for connections. */ listen (socket_fd, 5); /* Repeatedly accept connections, spinning off one server() to deal with each client. Continue until a client sends a “quit” message. */ do { struct sockaddr_un client_name; socklen_t client_name_len; int client_socket_fd; /* Accept a connection. */ client_socket_fd = accept (socket_fd, &client_name, &client_name_len); /* Handle the connection. */ client_sent_quit_message = server (client_socket_fd); /* Close our end of the connection. */ close (client_socket_fd); } while (!client_sent_quit_message); /* Remove the socket file. */ close (socket_fd); unlink (socket_name); return 0; } (socket-client.c) Local Namespace Socket Client #include #include #include #include #include /* Write TEXT to the socket given by file descriptor SOCKET_FD. */ void write_text (int socket_fd, const char* text) { /* Write the number of bytes in the string, including NUL-termination. */ int length = strlen (text) + 1; write (socket_fd, &length, sizeof (length)); /* Write the string. */ write (socket_fd, text, length); } int main (int argc, char* const argv[]) { const char* const socket_name = argv[1]; const char* const message = argv[2]; int socket_fd; struct sockaddr_un name; /* Create the socket. */ socket_fd = socket (PF_LOCAL, SOCK_STREAM, 0); /* Store the server’s name in the socket address. */ name.sun_family = AF_LOCAL; strcpy (name.sun_path, socket_name); /* Connect the socket. */ connect (socket_fd, &name, SUN_LEN (&name)); /* Write the text on the command line to the socket. */ write_text (socket_fd, message); close (socket_fd); return 0; } |
(socket-inet.c) Read from a WWW Server #include #include #include #include #include #include #include /* Print the contents of the home page for the server’s socket. Return an indication of success. */ void get_home_page (int socket_fd) { char buffer[10000]; ssize_t number_characters_read; /* Send the HTTP GET command for the home page. */ sprintf (buffer, “GET //n”); write (socket_fd, buffer, strlen (buffer)); /* Read from the socket. The call to read may not return all the data at one time, so keep trying until we run out. */ while (1) { number_characters_read = read (socket_fd, buffer, 10000); if (number_characters_read == 0) return; /* Write the data to standard output. */ fwrite (buffer, sizeof (char), number_characters_read, stdout); } } int main (int argc, char* const argv[]) { int socket_fd; struct sockaddr_in name; struct hostent* hostinfo; /* Create the socket. */ socket_fd = socket (PF_INET, SOCK_STREAM, 0); /* Store the server’s name in the socket address. */ name.sin_family = AF_INET; /* Convert from strings to numbers. */ hostinfo = gethostbyname (argv[1]); if (hostinfo == NULL) return 1; else name.sin_addr = *((struct in_addr *) hostinfo->h_addr); /* Web servers use port 80. */ name.sin_port = htons (80); /* Connect to the Web server */ if (connect (socket_fd, &name, sizeof (struct sockaddr_in)) == -1) { perror (“connect”); return 1; } /* Retrieve the server’s home page. */ get_home_page (socket_fd); return 0; } |