man
命令查詢相關的系統內核函數man
命令可知,對於最後一個shmop函數的解釋就是shmat函數:
int shmget(key_t key, size_t size, int shmflg):共享內存的創建或者打開linux
void shmat(int shmid,const void shmaddr,int shmflg):將一個共享內存空間映射到調用進程的地址空間上,返回在進程地址空間中的地址。用戶能夠經過這個地址間接的訪問共享內存安全
int shmdt(const void* shmaddr):將一個進程已經映射了的共享內存脫離進程地址空間服務器
int shmctl(int shmid, int cmd, struct shmid_ds *buf):刪除已建立好的共享內存數據結構
運行代碼函數
#include <stdio.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/shm.h> #include <string.h> #include <errno.h> typedef struct _Teacher { char name[64]; int age; }Teacher; int main(int argc, char *argv[]) { int ret = 0; int shmid; shmid = shmget(0x2234, sizeof(Teacher), IPC_CREAT | 0666); if (shmid == -1) { perror("shmget err"); return errno; } printf("shmid:%d \n", shmid); Teacher *p = NULL; //將共享內存段鏈接到進程地址空間 p = shmat(shmid, NULL, 0);//第二個參數shmaddr爲NULL,核心自動選擇一個地址 if (p == (void *)-1 ) { perror("shmget err"); return errno; } strcpy(p->name, "aaaa"); p->age = 33; //將共享內存段與當前進程脫離 shmdt(p); int num; scanf("%d", &num); if (num == 1) { //用於控制共享內存 ret = shmctl(shmid, IPC_RMID, NULL);//IPC_RMID爲刪除內存段 if (ret < 0) { perror("rmerrr\n"); } } return 0; }
#include <stdio.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/shm.h> #include <string.h> #include <errno.h> typedef struct _Teacher { char name[64]; int age; }Teacher; int main(int argc, char *argv[]) { int ret = 0; int shmid; //shmid = shmget(0x2234, sizeof(Teacher), IPC_CREAT |IPC_EXCL | 0666); //打開獲取共享內存 shmid = shmget(0x2234, 0, 0); if (shmid == -1) { perror("shmget err"); return errno; } printf("shmid:%d \n", shmid); Teacher *p = NULL; //將共享內存段鏈接到進程地址空間 p = shmat(shmid, NULL, 0); if (p == (void *)-1 ) { perror("shmget err"); return errno; } printf("name:%s\n", p->name); printf("age:%d \n", p->age); //將共享內存段與當前進程脫離 shmdt(p); int num; scanf("%d", &num); if (num == 1) { pause(); } return 0; }
管道:它是父進程和子進程間,或是子進程與子進程間單向的通信機制,即一個進程發送數據到管道,另一個進程從管道中讀出數據。若是須要雙向,或是多項通訊機制,則須要創建兩個或者多個管道
設計
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <fcntl.h> #define FIFO_NAME "/tmp/myfifo2" //定義宏,指向管道文件位置 #define TEN_MEG ( 1024*1024*10 ) //文件緩衝區最大值 int main( int argc, char* argv[ ] ) { int res; int c; int pipe_fd; int open_mode = O_WRONLY; //設置讀寫權限 int bytes_send = 0; if( access( FIFO_NAME, F_OK ) == -1 ) { //F_OK : 檢查是否有這個文件; 相似還有檢查文件可讀等,參見man中access中定義 res = mkfifo( FIFO_NAME, 0777 ); //建立管道文件,文件屬性爲0777,root可讀寫 if( res != 0 ){ //管道文件不可重名 printf( "Could not create fifo %s ", FIFO_NAME ); exit( 1 ); } } pipe_fd = open( FIFO_NAME, open_mode ); //打開管道,並設置打開權限 if( pipe_fd !=-1 ){ while( (c = getchar( )) > 0 ){ res = write( pipe_fd, &c, 1 ); //向管道中寫數據 if( res == -1 ){ perror( "write error" ); close( pipe_fd ); exit( 1 ); } } close( pipe_fd ); } return 0; }
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <fcntl.h> #include <sys/wait.h> #include <signal.h> #define FIFO_NAME "/tmp/myfifo2" //定義宏,指向管道文件的位置 void read_pipe(){ //子進程, 處理從管道中讀數據 int pipe_fd; int res; int c; int open_mode = O_RDONLY; //設置權限,爲只讀 pipe_fd = open( FIFO_NAME, open_mode ); //打開管道文件,並設置打開權限,返回int if( pipe_fd!=-1 ){ while(1){ while( (res = read( pipe_fd, &c, 1 )) > 0 ){ //從管道讀數據 putchar( c ); } fflush( stdout ); } }else{ exit( 1 ); } close(pipe_fd); } void signal_handler( int n){ //受到子進程退出信號,結束子進程 int child_status; wait( &child_status ); printf( "child exited. " ); } int main( int argc, char *argv[ ] ) { int pid; int child_status; signal(SIGCHLD, signal_handler); //子進程退出時所發信號 pid = fork(); //建立子進程,使之讀取管道數據 int i = 0; switch(pid){ case -1: printf("fork error"); exit( 1 ); case 0: read_pipe(); exit( 0 ); default: //作它本身無聊的事 for(i;i<100;i++){ printf("%d ", i); fflush( stdout ); sleep(2); } } return 0; }
FIFO
code
寫入數據blog
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <limits.h> #include <sys/types.h> #include <sys/stat.h> #define FIFO_NAME "/tmp/my_fifo" #define BUFFER_SIZE PIPE_BUF #define TEN_MEG (1024 * 1024 * 10) int main() { int pipe_fd; int res; int open_mode = O_WRONLY; int bytes_sent = 0; char buffer[BUFFER_SIZE + 1]; /* 檢查FIFO_NAME文件是否存在,若是不存在就建立它 */ if (access(FIFO_NAME, F_OK) == -1) { /* mkfifo建立命名管道(即特殊類型的文件FIFO) */ res = mkfifo(FIFO_NAME, 0777); if (res != 0) { fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME); exit(EXIT_FAILURE); } } printf("Process %d opening FIFO_OWRONLY\n", getpid()); /* open函數以O_WRONLY方式打開FIFO文件,若是成功pipe_fd指向打開的文件 */ pipe_fd = open(FIFO_NAME, open_mode); printf("Process %d result %d\n", getpid(), pipe_fd); if (pipe_fd != -1) { /* */ while(bytes_sent < TEN_MEG) { /* write函數從buffer指向的內存中寫入BUFFER_SIZE個字節到pipe_fd文件中 * 若是成功則返回實際寫入的字節數 */ res = write(pipe_fd, buffer, BUFFER_SIZE); if (res == -1) { fprintf(stderr, "Write error on pipe\n"); exit(EXIT_FAILURE); } bytes_sent += res; } (void)close(pipe_fd); } else { exit(EXIT_FAILURE); } printf("Process %d finished\n", getpid()); exit(EXIT_SUCCESS); }
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <limits.h> #include <sys/types.h> #include <sys/stat.h> #define FIFO_NAME "/tmp/my_fifo" #define BUFFER_SIZE PIPE_BUF int main() { int pipe_fd; int res; int open_mode = O_RDONLY; char buffer[BUFFER_SIZE + 1]; int bytes_read = 0; memset(buffer, '\0', sizeof(buffer)); printf("Process %d opening FIFO O_RDONLY\n", getpid()); /* open函數打開FIFO_NAME文件,以open_mode的方式(即O_RDONLY) * 若是成功,則返回文件描述符 */ pipe_fd = open(FIFO_NAME, open_mode); printf("Process %d result %d\n", getpid(), pipe_fd); if (pipe_fd != -1) { do { /* read函數從pipe_fd指向的文件中讀入BUFFER_SIZE個字節的數據到buffer指向的內存 * 若是成功,返回實際讀入數據的字節數 */ res = read(pipe_fd, buffer, BUFFER_SIZE); bytes_read += res; } while (res > 0); (void)close(pipe_fd); } else { exit(EXIT_FAILURE); } printf("Process %d finished, %d bytes read\n", getpid(), bytes_read); exit(EXIT_SUCCESS); }
#include <stdio.h> #include <sys/types.h> #include <stdlib.h> #include <signal.h> void func(int sig) { printf("I get a signal!\n"); } int main() { char buffer[100]; struct sigaction act; act.sa_handler=func; sigemptyset(&act.sa_mask); act.sa_flags = 0; if(sigaction(SIGINT,&act, NULL) == -1) { printf("sigaction error exit now\n"); exit(0); } printf("pid:%ld\n",(long)getpid()); while(1) { fgets(buffer,sizeof(buffer),stdin); printf("buffer is:%s\n",buffer); } return 0; }
Ctrl+C
中斷進程每一個數據塊都被認爲含有一個類型,接收進程能夠獨立地接收含有不一樣類型的數據結構。能夠經過發送消息來避免命名管道的同步和阻塞問題隊列
例子進程
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/msg.h> #include <errno.h> #define MAX_TEXT 512 struct msg_st { long int msg_type; char text[MAX_TEXT]; }; int main() { int running = 1; struct msg_st data; char buffer[BUFSIZ]; int msgid = -1; //創建消息隊列 msgid = msgget((key_t)1234, 0666 | IPC_CREAT); if(msgid == -1) { fprintf(stderr, "msgget failed with error: %d\n", errno); exit(EXIT_FAILURE); } //向消息隊列中寫消息,直到寫入end while(running) { //輸入數據 printf("Enter some text: "); fgets(buffer, BUFSIZ, stdin); data.msg_type = 1; //注意2 strcpy(data.text, buffer); //向隊列發送數據 if(msgsnd(msgid, (void*)&data, MAX_TEXT, 0) == -1) { fprintf(stderr, "msgsnd failed\n"); exit(EXIT_FAILURE); } //輸入end結束輸入 if(strncmp(buffer, "end", 3) == 0) running = 0; sleep(1); } exit(EXIT_SUCCESS); }
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <sys/msg.h> struct msg_st { long int msg_type; char text[BUFSIZ]; }; int main() { int running = 1; int msgid = -1; struct msg_st data; long int msgtype = 0; //注意1 //創建消息隊列 msgid = msgget((key_t)1234, 0666 | IPC_CREAT); if(msgid == -1) { fprintf(stderr, "msgget failed with error: %d\n", errno); exit(EXIT_FAILURE); } //從隊列中獲取消息,直到遇到end消息爲止 while(running) { if(msgrcv(msgid, (void*)&data, BUFSIZ, msgtype, 0) == -1) { fprintf(stderr, "msgrcv failed with errno: %d\n", errno); exit(EXIT_FAILURE); } printf("You wrote: %s\n",data.text); //遇到end結束 if(strncmp(data.text, "end", 3) == 0) running = 0; } //刪除消息隊列 if(msgctl(msgid, IPC_RMID, 0) == -1) { fprintf(stderr, "msgctl(IPC_RMID) failed\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }