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); }