Linux-C-day-4-進(jìn)程間通信-消息隊(duì)列||信號(hào)量 ||共享內(nèi)存

消息隊(duì)列

消息隊(duì)列是在內(nèi)核中實(shí)現(xiàn)的偶垮,并且是具有一定的優(yōu)先級(jí)的一種進(jìn)程間通信模型

POSIX PIC消息隊(duì)列

在unpv22e遗增,ch 5.1--5.5可以查看這些知識(shí)叫惊,POSIX消息隊(duì)列使用的頭函數(shù)是mqueue.h;使用的庫(kù)文件為librt.so做修;消息隊(duì)列通過(guò)結(jié)構(gòu)體:struct mq_arrt 來(lái)定義消息隊(duì)列屬性霍狰,結(jié)構(gòu)體中選項(xiàng)包含的有:mq_flags:標(biāo)志抡草,在mq_open時(shí)被初始化,mq_setattr可以進(jìn)行設(shè)置蔗坯;這個(gè)值通常為0或者O_NONBLOCK康震;mq_maxmsg:表示的是隊(duì)列中消息的最大個(gè)數(shù),只能在mq_open時(shí)被初始化宾濒;mq_msgsize:表示隊(duì)列中每個(gè)消息的最大值腿短;mq_curmsgs:表示當(dāng)前隊(duì)列消息長(zhǎng)度,在mq_getattr 時(shí)進(jìn)行獲榷κ蕖答姥;
關(guān)于消息隊(duì)列的八種操作:
?創(chuàng)建消息隊(duì)列:mqd_t mq_open(const char *name, int oflag,mode_t mode,struct mq_attr *attr);name:表示posix IPC名字谚咬;oflag:表示標(biāo)志鹦付,O_CREAT:表示在沒(méi)有時(shí),創(chuàng)建該對(duì)象择卦;O_EXCL:表示如果O_CREAT指定敲长,但是name不存在,就返回錯(cuò)誤信息秉继;O_NONBLOCK:表示以非阻塞方式打開(kāi)消息隊(duì)列祈噪;O_RDONLY:表示只讀;O_RDWR:表示讀寫尚辑;O_WRONLY:表示只寫辑鲤;mode:權(quán)限:S_IWUSR:表示用戶屬主寫權(quán)限;S_IRUSR:表示用戶屬主讀權(quán)限杠茬;S_IWGRP:表示組成員寫權(quán)限月褥;S_IRGRP:表示組成員讀權(quán)限;S_IWOTH:其他用戶寫權(quán)限瓢喉;S_IROTH:表示其他用戶讀權(quán)限宁赤;attr:表示隊(duì)列屬性:attr.mq_falg = 0;表示阻塞;attr.mq_flag = NONBLOCK栓票,表示非阻塞决左;返回值:-1,表示出錯(cuò)走贪;返回值為其他表示消息隊(duì)列描述符佛猛;
mqcreate.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <mqueue.h>
#include <fcntl.h>
#include <sys/stat.h>
#define FILE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH) //0644
int main(int argc,char* argv[]){
    int c,flag=0;
    long maxmsg = 10;
    long msglen = 8192;
    while((c=getopt(argc,argv,"q:l:"))!=-1){
        switch(c){
        case 'q':
            maxmsg = atoi(optarg);
            break;
        case 'l':
            msglen = atoi(optarg);
            break;
        }
    }

    if(optind != argc-1){
        printf("usage:%s [-q <maxmsg>] [-l <msglen>] <mqname>\n",argv[0]);
        return 1;
    }
    struct mq_attr attr;
    attr.mq_maxmsg = maxmsg;
    attr.mq_msgsize = msglen;
    mqd_t mqd = mq_open(argv[optind],O_CREAT,FILE_MODE,&attr);
    if(-1 == mqd){
        perror("mq_open error");
        return 1;
    }
}

刪除消息隊(duì)列:int mq_unlink(const char *name);name:表示posixIPC名字坠狡;返回值-1表示失敗挚躯,0表示成功;
mq_unlink.c

#include <stdio.h>
#include <stdlib.h>
#include <mqueue.h>
#include <fcntl.h>
#include <sys/stat.h>
int main(){
    mq_unlink("/tmp.test");
}

打開(kāi)消息隊(duì)列:mqd_t mq_open(const char *name,int oflag)擦秽;name:posix IPC表示名字码荔;oflag:表示標(biāo)志位漩勤,O_RDONLY,只讀缩搅;O_RDWR:表示讀寫越败;O_WRONLY:表示只寫;返回值為-1時(shí)表示出錯(cuò)硼瓣,返回值為其他表示描述符究飞;
隊(duì)列的打開(kāi)函數(shù)一般和發(fā)送或者接收一起出現(xiàn),就寫在一個(gè)函數(shù)里面堂鲤;
?關(guān)閉消息隊(duì)列:int mq_close(mqd_t mqdes);其中mqdes表示消息隊(duì)列描述符亿傅;返回值-1表示出錯(cuò),0表示成功瘟栖;
?設(shè)置消息隊(duì)列屬性:int mq_setattr(mqd_t mqdes,struct mq_attr *newattr,struct mq_attr *oldattr)葵擎;mqdes:表示消息隊(duì)列描述符;newattr:用于設(shè)置新屬性半哟,但是只能用于設(shè)置mq_falgs酬滤,其中0表示阻塞,NONBLOCK表示非阻塞寓涨;
oldattr:表示用于設(shè)置舊屬性盯串;函數(shù)返回值-1表示出錯(cuò),返回值0表示成功戒良;
mqsetattr.c:

#include <stdio.h>
#include <stdlib.h>
#include <mqueue.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
int main(){
    mqd_t mqd = mq_open("/tmp.test",O_RDWR);
    if(-1 == mqd){
        perror("mq_open error");
        return;
    }
    struct mq_attr new_attr;
    bzero(&new_attr,sizeof(new_attr));

    new_attr.mq_flags = O_NONBLOCK;
    struct mq_attr attr;
    if(-1 == mq_setattr(mqd,&new_attr,&attr)){
        perror("mq_setattr error");
        return 1;
    }
    printf("flag:%ld,Max msg:%ld,Max msgsize:%ld,Cur msgnun:%ld\n",attr.mq_flags,attr.mq_maxmsg,attr.mq_msgsize,attr.mq_curmsgs);
}

獲取消息隊(duì)列屬性:int mq_getattr(mqd_t mqdes, struct mqdes,struct mq_attr *attr)体捏;mqdes:表示消息隊(duì)列描述符;attr:表示屬性信息糯崎;返回值:-1表示出錯(cuò)信息译打;0表示成功;
mqgetattr.c

#include <stdio.h>
#include <stdlib.h>
#include <mqueue.h>
#include <fcntl.h>
#include <sys/stat.h>
int main(int argc,char* argv[]){
    mqd_t mqd = mq_open(argv[1],O_RDONLY);
    if(-1 == mqd){
        perror("mq_open error");
        return;
    }
    struct mq_attr attr;
    mq_getattr(mqd,&attr);
    printf("flag:%ld,Max msg:%ld,Max msgsize:%ld,Cur msgnun:%ld\n",attr.mq_flags,attr.mq_maxmsg,attr.mq_msgsize,attr.mq_curmsgs);
}

發(fā)送消息:int mq_send(mqd_t mqdes,const char *msg_ptr,size_t msg_len,unsigned msg_prio)拇颅;msg_ptr:表示消息隊(duì)列的指針;msg_len:表示消息長(zhǎng)度乔询,但是不能大于屬性值mq_msgsize的值樟插;msg_prio:表示優(yōu)先級(jí),消息在隊(duì)列中將按照優(yōu)先級(jí)大小順序來(lái)排列消息竿刁;如果消息隊(duì)列已滿黄锤,mq_send()函數(shù)將阻塞,知道油客埇的空間再次允許放置消息食拜;如果O_NONBLOCK被指定鸵熟,mq_send()那么將不會(huì)被阻塞,而是返回EAGAIN的值负甸;
mqsnd.c:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <mqueue.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#define FILE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH) //0644
int main(int argc,char* argv[]){
    int c,flags=O_WRONLY;
    while((c=getopt(argc,argv,"n"))!=-1){
        switch(c){
        case 'n':
            flags|=O_NONBLOCK;
            break;
        }
    }
    if(optind != argc-1){
        printf("usage:%s [-n] <mqname> <message> <prio>\n");
        return 1;
    }
    mqd_t mqd = mq_open(argv[optind],flags);
    if(-1 == mqd){
        perror("mq_open error");
        return 1;
    }
    if(-1 == mq_send(mqd,argv[optind+1],strlen(argv[optind+1])+1,atoi(argv[optind+2]))){
        perror("mq_send error");
        return 1;
    }
}

接收消息:ssize_t mq_recceive(mqd_t mqdes流强,char *msg_ptr痹届,size_t msg_len,unsigned *msg_len打月,unsigned *msg_prio);msg_prt:表示消息隊(duì)列的指針队腐;msg_len:表示消息長(zhǎng)度,不能夠大于屬性值mq_msgsize的值奏篙;msg_prio:表示優(yōu)先級(jí)柴淘,消息在隊(duì)列中將按照優(yōu)先級(jí)大小順序來(lái)排列消息;返回值:-1表示出錯(cuò)秘通,正數(shù)表示接收到消息的長(zhǎng)度为严;如果隊(duì)列為空,mq_receive()函數(shù)將阻塞肺稀,知道消息隊(duì)列中有新的消息第股。如果O_NONBLOCK被指定,mq_receive()將不會(huì)阻塞盹靴,而是返回EAGAIN錯(cuò)誤炸茧;
mqrecv.c:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <mqueue.h>
#include <fcntl.h>
#include <sys/stat.h>
#define FILE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH) //0644
int main(int argc,char* argv[]){
    int c,flags=O_RDONLY;
    while((c=getopt(argc,argv,"n"))!=-1){
        switch(c){
        case 'n':
            flags|=O_NONBLOCK;
            break;
        }
    }
    if(optind != argc-1){
        printf("usage:%s [-n] <mqname>\n");
        return 1;
    }
    mqd_t mqd = mq_open(argv[optind],flags);
    if(-1 == mqd){
        perror("mq_open error");
        return 1;
    }
    char buf[BUFSIZ];
    int prio;
    if(-1 == mq_receive(mqd,buf,BUFSIZ,&prio)){
        perror("mq_send error");
        return 1;
    }
    printf("msg:%s\nprio:%d\n",buf,prio);
}

對(duì)于共享內(nèi)存的查看:man mq_overview,ls /dev/mqueue稿静;cat /dev/mqueue/PIC名字梭冠;

POSIX共享內(nèi)存

需要包含的頭文件sys/mman.h 需要包含的庫(kù)文件是librt.so
創(chuàng)建共享內(nèi)存:int shm_open(const char *name,int oflag,mode_t mode);name:表示posix IPC的名字;ofloag:表示標(biāo)志改备,O_CREAT:表示沒(méi)有的話控漠,創(chuàng)建該對(duì)象;
O_EXCL:如果O_CREAT指定悬钳,但是name不存在盐捷,就返回錯(cuò)誤;O_RDONLY:表示只讀默勾;O_RDWR:表示讀寫碉渡;O_TRUNC:表示如果存在就截?cái)啵籱ode:表示權(quán)限:S_IWUSR:表示用戶/屬主寫權(quán)限母剥;S_IRUSR:表示用戶/屬主讀權(quán)限滞诺;S_IR、WGRP:表示組成員寫權(quán)限环疼;S_IRGRP:表示組成員讀權(quán)限习霹;S_IWOTH:表示其他用戶寫權(quán)限;S_IROTH:表示其他用戶讀權(quán)限炫隶;函數(shù)的返回值-1表示出錯(cuò)淋叶;返回值為其他表示共享內(nèi)存描述符;
shmcreate.c

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

int main(int argc,char* argv[]){
    int fd = shm_open(argv[1],O_CREAT|O_RDWR,0644);
    ftruncate(fd,atoi(argv[2]));
    void* buf = NULL;
    if(( buf =  mmap(NULL,BUFSIZ,PROT_WRITE,MAP_SHARED,fd,0)) == MAP_FAILED){
        perror("mmap error\n");
        return 1;
    }
}

刪除int shm_unlink(const char *name)伪阶;name:表示posix IPC名字煞檩;返回值:-1表示出錯(cuò)处嫌,0表示成功;
shmunlink.c

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

int main(int argc,char* argv[]){
    shm_unlink(argv[1]);
}

修改文件的大行谓俊:int fruncate(int fd, off_t lenght)锰霜,fd:表示文件描述符;length:表示文件大小桐早,如果原來(lái)的文件帶下比參數(shù)length大癣缅,超過(guò)的部分就會(huì)被刪除;返回值:0表示成功哄酝;-1:失斢汛妗;這個(gè)函數(shù)用戶設(shè)置共享內(nèi)存的大小陶衅,fruncate(fd,len);
fruncate.c:

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

int main(int argc,char* argv[]){
    int fd = shm_open(argv[1],O_CREAT|O_RDWR,0644);
    ftruncate(fd,atoi(argv[2]));
    void* buf = NULL;
    if(( buf =  mmap(NULL,BUFSIZ,PROT_WRITE,MAP_SHARED,fd,0)) == MAP_FAILED){
        perror("mmap error\n");
        return 1;
    }
}

獲取文件信息:int fstat(int fd,struct stat *buf)屡立,fd:表示文件描述符;buf:是一個(gè)結(jié)構(gòu)體搀军,里面的參數(shù)分別表示:st_mode:表示文件對(duì)應(yīng)的模式膨俐,文件,目錄等罩句;st_size:表示普通文件焚刺,對(duì)應(yīng)的文件字節(jié)數(shù);st_atime:文件最后被訪問(wèn)的時(shí)間门烂;st_mtime:文件最后被修改訪問(wèn)的時(shí)間乳愉;st_ctime:文件狀態(tài)改變的時(shí)間;st_uid:文件所有者屯远;st_gid:文件所有者對(duì)應(yīng)的組蔓姚;st_blksize:文件內(nèi)容對(duì)應(yīng)的塊大小慨丐;st_blksize:文件內(nèi)容對(duì)應(yīng)的塊大衅缕辍;st_blocks:內(nèi)容對(duì)應(yīng)的塊數(shù)量房揭;st_ino:inode節(jié)點(diǎn)號(hào)备闲;st_dev:設(shè)備號(hào)碼;st_rdev:特殊設(shè)備號(hào)碼崩溪;st_nlink:文件的連接數(shù);
?st_mode:S_IFREG:表示一般文件斩松;S_IFDIR:表示目錄伶唯;S_IFSOCK:表示socket文件;S_IFIFO:表示先進(jìn)先出惧盹;S_IFLINK:表示符號(hào)鏈接乳幸;S_IFCHR:表示字符設(shè)置瞪讼;可以使用這些宏定義來(lái)判斷文件的類型;S_ISLINK(st_mode)粹断,S_ISREG(st_mode):判斷是否為一般文件符欠;S_ISDIR(st_mode):判斷是否為目錄;S_ISCHR(st_mode):判斷是否為字符文件瓶埋;S_ISBLK(st_mode):判斷是否為先進(jìn)先出文件希柿;S_ISSOCK(st_mode):判斷是否為socket;S_IFMT:文件類型的位遮罩养筒;S_IFBLK:區(qū)塊裝置曾撤;S_IUID:文件的(set user-id on execution)位;S_ISGID:文件的(set group-id on execution)晕粪;S_ISVTX:文件的sticky位挤悉;
?st_size:表示文件的大小巫湘;st_uid:表示屬主ID装悲;st_uid:屬主ID;st_guid:表示組ID尚氛;
?返回值:0表示成功诀诊;-1表示失敗怠褐;
暫時(shí)沒(méi)有代碼文件畏梆;
?建立內(nèi)存映射:void * mmap(void * start,size_t length, int prot,int flags, int fd, off_t offset):start:映射區(qū)的開(kāi)始地址,參數(shù)如果設(shè)置成NULL奈懒,表示有系統(tǒng)設(shè)置映射區(qū)的起始地址奠涌,如果考慮系統(tǒng)的可移植性,必須設(shè)置成為NULL磷杏;lenght:表示映射區(qū)的長(zhǎng)度溜畅,單位是字節(jié),但不足一頁(yè)按照一頁(yè)內(nèi)存進(jìn)行處理极祸;prot:內(nèi)存保護(hù)裝置 慈格;PROT_EXEC:表示頁(yè)內(nèi)容可以被執(zhí)行;PROT_READ:表示頁(yè)內(nèi)容可以被讀纫=稹浴捆;PROT_WAITE:表示頁(yè)面內(nèi)容可以被寫入;PROT_NONE:表示頁(yè)面內(nèi)容不可以被訪問(wèn)稿械;但是不能夠與文件的打開(kāi)模式?jīng)_突选泻;flags:映射對(duì)象的類型,MAP_SHARED:表示變動(dòng)共享;MAP_PRIVATE:表示變動(dòng)私有页眯;MAP_ANON:匿名內(nèi)存映射梯捕;fd:文件描述符,不能使套接字和中斷的fd窝撵,-1表示匿名內(nèi)存映射傀顾;
off_toset:表示被映射對(duì)象內(nèi)容的起點(diǎn);返回值:MAP_FAILED:表示失斅捣睢短曾;非MAP_FAILED:表示共享內(nèi)存地址;
mmapcreate.c

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

int main(int argc,char* argv[]){
    int fd = open("./mmap.txt",O_CREAT|O_RDWR,0644);
    char str[] = "hello mmap\n";    
    lseek(fd,sizeof(str),SEEK_SET);
    char* end = "\0";
    write(fd,end,1);
    void* buf = NULL;
    if(( buf =  mmap(NULL,sizeof(str),PROT_WRITE,MAP_SHARED,fd,0)) == MAP_FAILED){
        perror("mmap error\n");
        return 1;
    }
    strcpy(buf,str);
    munmap(buf,sizeof(str));
    close(fd);
}

mmapcreate02.c

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

int main(int argc,char* argv[]){
    int fd = open("./mmap.txt",O_RDWR);
    void* buf = NULL;
    if(( buf =  mmap(NULL,BUFSIZ,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0)) == MAP_FAILED){
        perror("mmap error\n");
        return 1;
    }
    printf("%s\n",buf);
    strcpy(buf,"this sdfdsfdsfdsfdsfdsfdsfdsfdsfdsf\n");
    munmap(buf,BUFSIZ);
    close(fd);
}

mmapcreate03.c

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

int main(int argc,char* argv[]){
    int fd = open("./mmap.txt",O_CREAT|O_RDWR,0644);
    char str[] = "hello mmap\n";    
    lseek(fd,sizeof(str),SEEK_SET);
    char* end = "\0";
    write(fd,end,1);
    void* buf = NULL;
    if(( buf =  mmap(NULL,sizeof(str),PROT_WRITE,MAP_SHARED,fd,0)) == MAP_FAILED){
        perror("mmap error\n");
        return 1;
    }
    strcpy(buf,str);
    pause();
//  munmap(str,sizeof(str));
//  close(fd);
    //_exit(0);
}

mmapcreate04.c

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

int main(int argc,char* argv[]){
    int fd = open("./mmap.txt",O_CREAT|O_RDWR,0644);
    void* buf = NULL;
    if(( buf =  mmap(NULL,BUFSIZ,PROT_WRITE|PROT_READ,MAP_SHARED,fd,0)) == MAP_FAILED){
        perror("mmap error\n");
        return 1;
    }
    if(fork()){
        strcpy(buf,argv[1]);    
    }else{
        printf("%s\n",buf);
    }
    munmap(buf,BUFSIZ);
    close(fd);
}

刪除內(nèi)存映射int munmap(void *start,size_t length)道批;start:映射內(nèi)存起始地址错英;length:表示內(nèi)存大小隆豹;返回值:0表示成功椭岩,-1表示失敗璃赡;需要注意的是關(guān)閉mmap中的文件描述符不能刪除內(nèi)存映射判哥;

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

int main(int argc,char* argv[]){
    int fd = open("./mmap.txt",O_CREAT|O_RDWR,0644);
    char str[] = "hello mmap\n";    
    lseek(fd,sizeof(str),SEEK_SET);
    char* end = "\0";
    write(fd,end,1);
    void* buf = NULL;
    if(( buf =  mmap(NULL,sizeof(str),PROT_WRITE,MAP_SHARED,fd,0)) == MAP_FAILED){
        perror("mmap error\n");
        return 1;
    }
    strcpy(buf,str);
    munmap(buf,sizeof(str));//表示的含義就是刪除內(nèi)存映射
    close(fd);
}

同步操作:int msync(void * addr,size_t len,int flags);addr:表示映射內(nèi)存起始地址碉考;len:表示內(nèi)存大兴啤;flags:表示同步參數(shù)侯谁,MX_ASYNC锌仅,調(diào)用會(huì)立即返回,不等到跟新的完成墙贱,MS_SYNC:表示同步热芹,調(diào)用會(huì)等到更新完成之后返回;MS_INVALIDATE:通知使用該共享區(qū)域的進(jìn)程惨撇,數(shù)據(jù)已經(jīng)改變伊脓;在共享內(nèi)容更改之后,是的文件的其他映射失效魁衙;返回值:0:表示成功报腔;-1表示失敗剖淀;和文件的fflush相似纯蛾;
?查看:man shm_overview;ls /dev/shm纵隔;注意的是msg_open默認(rèn)生成共享內(nèi)存的大小是0翻诉,需要ftuncate設(shè)置大蟹俊;

POSIX信號(hào)量

資料可以查看unv22e米丘,頭文件是semaphore.h需要鏈接的庫(kù)文件是pthread;信號(hào)量類似于停車場(chǎng)的電子牌糊啡,信號(hào)量可以分為二值信號(hào)量拄查,0和1;計(jì)數(shù)信號(hào)量0和n棚蓄;信號(hào)量適用于控制多進(jìn)程訪問(wèn)共享資源的堕扶;
?信號(hào):P信號(hào):0表示掛起進(jìn)程;>0時(shí)梭依,減1稍算;V信號(hào):0表示恢復(fù)進(jìn)程;>0:表示加1役拴;信號(hào)的本質(zhì)是在任一時(shí)刻只能有一個(gè)進(jìn)程訪問(wèn)臨界區(qū)糊探;

命名信號(hào)量/基于文件

創(chuàng)建:sem_t *sem_open(const char *name, int oflag,mode_t mode, unsigned int value);name:信號(hào)量IPC 名字河闰;oflag:O_CREAT:如果沒(méi)有這些對(duì)象就創(chuàng)建這個(gè)對(duì)象科平;O_EXCL:如果O_CREAT指定,但是name不存在姜性,就返回錯(cuò)誤瞪慧;mode:表示權(quán)限位;value:信號(hào)量初始值部念;返回值:非SEM_FAILED:信號(hào)量的指針弃酌;SEM_FAILED:出錯(cuò);
semopen.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <semaphore.h>

int main(int argc,char * argv[]){

    sem_t* sem = sem_open(argv[1],O_CREAT|O_RDWR,0644,0);
    fork();
    int i=0;
    for(;i<5;i++){
        sleep(1);
        sem_wait(sem);
        printf("PID:%d,enter\n",getpid());
        printf("PID:%d,do something\n",getpid());
        printf("PID:%d,leave\n",getpid());
        sem_post(sem);
    }
}

打開(kāi):sem_t *sem_open(const char *name,int oflag)儡炼;sem_t *sem_open(const char *name,int oflag):name:信號(hào)量IPC名字妓湘;oflag:0;返回值:非SEM_FAILED:信號(hào)量的指針射赛;SEM_FAILED:出錯(cuò)多柑;

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <semaphore.h>

int main(int argc,char * argv[]){

    sem_t* sem = sem_open(argv[1],O_CREAT|O_RDWR,0644,0);
    fork();
    int i=0;
    for(;i<5;i++){
        sleep(1);
        sem_wait(sem);
        printf("PID:%d,enter\n",getpid());
        printf("PID:%d,do something\n",getpid());
        printf("PID:%d,leave\n",getpid());
        sem_post(sem);
    }
}

關(guān)閉:int sem_close(sem_t *sem);sem:信號(hào)量的指針楣责;返回值:-1表示出錯(cuò)竣灌,0表示成功;


刪除int sem_unlink(const char *name)秆麸;name:表示信號(hào)量IPC的名字初嘹;返回值-1出錯(cuò),0表示成功沮趣;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
無(wú)名信號(hào)量/基于內(nèi)存

初始化:int sem_init(sem_t *sem,int pshared,unsigned int value)屯烦;sem:表示信號(hào)量的指針;pshared:表示共享方式,0表示線程間共享驻龟,1表示進(jìn)程間共享温眉,但是需要共享內(nèi)存;value:信號(hào)量初始值翁狐;返回值:-1类溢,出錯(cuò),-表示成功露懒;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

銷毀:int sem_destory(sem_t *sem)闯冷,sem:表示信號(hào)量的指針;返回值位1表示出錯(cuò)懈词,0表示成功又官;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

掛出:int sem_post(sem_t *sem)赃蛛;sem:信號(hào)量的指針;返回值:-1表示出錯(cuò),0表示成功撼班;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

等待:int sem_wait(sem_t *sem)永淌;sem:表示信號(hào)量的指針粪般;返回值:-1表示出錯(cuò)察纯,0表示成功;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

嘗試等待:int sem_trywait(sem_t *sem)褐桌;sem:信號(hào)量的指針衰抑;返回值:-1表示出錯(cuò),0表示成功荧嵌;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

獲取信號(hào)量的值:int sem_getvalue(sem_t *sem,int *sval)呛踊;sem:信號(hào)量的指針;sval:信號(hào)量的值啦撮;返回值:0表示成功谭网,-1表示出錯(cuò);

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

查看man sem_overview
?標(biāo)識(shí)/名字赃春,路徑名 /tmp.123
幾種方式的對(duì)比:
創(chuàng)建:文件:mqd_t mq_open(const char *name,int oflag,mode_t mode)愉择;消息隊(duì)列:mqd_t mqopen(const char *name,int oflag,mode_t mode,struct mq_arrt, *attr)共享內(nèi)存:int shm_open(const char *name,int oflag,mode_t);信號(hào)量:sem_t *sem_open(const char *name,int oflag,mode_t mode,unsigned int value);
刪除:文件:int unlink(const char *name)织中;消息隊(duì)列:mqd_t mq_unlink(const char *name)锥涕;共享內(nèi)存:int shm_unlink(const char *name) 信號(hào)量:sem_t *sem_unlink(const char *name);

System V PIC

system V消息隊(duì)列

需要包含的頭文件是sys/msg.h狭吼,需要自定義的結(jié)構(gòu)體msgbuf层坠,其中包含兩個(gè)選項(xiàng):消息類型:必須是long,必須是結(jié)構(gòu)體的第一個(gè)變量刁笙,mtext:標(biāo)識(shí)消息數(shù)據(jù)破花,可以隨意定義谦趣;

相關(guān)函數(shù)

消息獲取:int msgget(key_t key, int msgflg)座每;key:IPC鍵前鹅,key_t ftok(char *path,int id),path峭梳,id嫡纠;IPC_PRIVATE:通常用于親緣進(jìn)程;msgflg:IPC_CREAT:標(biāo)識(shí)創(chuàng)建延赌;IPC_CREAT | IPC_EXCL;權(quán)限:建議使用八進(jìn)制數(shù)字來(lái)進(jìn)行描述叉橱;返回值非負(fù)整數(shù)標(biāo)識(shí)消息隊(duì)列標(biāo)識(shí)挫以,-1:標(biāo)識(shí)失敗窃祝;
msghget.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/msg.h>
struct msgbuf {
       long mtype;       /* message type, must be > 0 */
       char mtext[1];    /* message data */
   };

int main(){
    int id = msgget(IPC_PRIVATE,O_CREAT|O_RDWR|0644);
    if(-1 == id){
        perror("msgget error");
        return 1;
    }
    char str[] = "this is msg";
    struct msgbuf* buf = malloc(sizeof(str)+sizeof(long));
    buf->mtype= 10;
    strcpy(buf->mtext,str);
    if(fork()){
        msgsnd(id,buf,sizeof(str),0);
    }else{
        sleep(1);
        bzero(buf,sizeof(str)+sizeof(long));
        msgrcv(id,buf,sizeof(str),-11,0);
        printf("recv :%s",buf->mtext);
    }
    //msgctl(id,IPC_RMID,NULL);
}

消息發(fā)送:int msgsnd(int msgid,const void *msgptr,size_t msgsz,int msgflg)掐松;msgid:表示消息隊(duì)列標(biāo)識(shí);msgptr:表示消息結(jié)構(gòu)體粪小,是以一個(gè)長(zhǎng)整型成員變量開(kāi)始的結(jié)構(gòu)體大磺,

struct test_messsge{
          long mtype; //must > 0
          char mtext;// data;
};

msgsz:表示消息隊(duì)列長(zhǎng)度,但是不包括長(zhǎng)整型變量探膊;msgflg:用于控制函數(shù)的行為杠愧,0表示忽略;IPC_NOWAIT:表示如果消息隊(duì)列為空逞壁,就返回一個(gè)ENOMSG流济,并將控制權(quán)教會(huì)個(gè)調(diào)用函數(shù)的進(jìn)程。MSG_NOERROR:如果函數(shù)取得的消息長(zhǎng)度大于msgsz腌闯,將只返回msgsz的長(zhǎng)度绳瘟,剩下的部分就被丟棄了。MSG_EXCEPT:當(dāng)msgtyp > 0時(shí)姿骏,接受的類型不扥估m(xù)sgtype的第一條消息糖声;返回值:表示成功,-1表示失敺质荨蘸泻;
msgsnd.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/msg.h>
#include <fcntl.h>
struct msgbuf{
    long mtype;
    char mtext[1];
};
int main(int argc,char* argv[]){
    int c,flag = 0;
    while((c = getopt(argc,argv,"n")) !=-1){
        switch(c){
        case 'n':
            flag=IPC_NOWAIT;
            break;
        }
    }
    if(optind != argc - 3){
        printf("usage:%s [-n] <pathname> <message> <type>\n",argv[0]);
        return 1;
    }

    int id = msgget(ftok(argv[optind],1),O_WRONLY);
    if(-1 == id){
        perror("msgget error");
        return 1;
    }
    size_t msglen = strlen(argv[optind+1])+1;
    struct msgbuf* buf = malloc(sizeof(long)+msglen);
    buf->mtype = atoi(argv[optind+2]);
    strcpy(buf->mtext,argv[optind+1]);
    
    if(-1 == msgsnd(id,buf,msglen,flag)){
        perror("fcntl error");
        return 1;
    }
}

接收消息:int msgrcv(int msgid,void *msgptr,size_t msgsz嘲玫,long msgtype蟋恬,int msgflg);msid:表示消息隊(duì)列標(biāo)識(shí)趁冈;msgptr:消息結(jié)構(gòu)體歼争,以一個(gè)長(zhǎng)整型成員變量開(kāi)始的結(jié)構(gòu)體拜马;

struct   test_message{
            long   int   message_type;  // the data you which to transfer;
};

msgtype:標(biāo)識(shí)消息的接收類型沐绒,0標(biāo)識(shí)消息隊(duì)列中的第一個(gè)消息俩莽,大于0標(biāo)識(shí)獲取具有相同消息類型的第一個(gè)消息;小于0標(biāo)識(shí)獲取類型等于或者小于msgtype的絕對(duì)值的最小一個(gè)消息乔遮;msgflg:用于控制函數(shù)的行為扮超,0標(biāo)識(shí)忽略,IPC_NOWAIT:如果消息隊(duì)列為空則返回一個(gè)ENOMSG蹋肮,并將控制權(quán)返回給調(diào)用函數(shù)的進(jìn)程出刷;MSG_NOERROR,如果函數(shù)取得的消息隊(duì)列長(zhǎng)度大于msgsz坯辩,將只返回msgsz長(zhǎng)度的信息馁龟,剩下的部分機(jī)會(huì)被丟棄;MSG_EXCEPT:當(dāng)msgtype > 0 時(shí)漆魔,接受的類型不等于msgtype的第一個(gè)條消息坷檩;返回值:0標(biāo)識(shí)接收到的消息長(zhǎng)度,-1失敻穆铡矢炼;
msgrecv.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/msg.h>
#include <fcntl.h>
struct msgbuf{
    long mtype;
    char mtext[1];
};
int main(int argc,char* argv[]){
    int c,flag = 0;
    while((c = getopt(argc,argv,"n")) !=-1){
        switch(c){
        case 'n':
            flag=IPC_NOWAIT;
            break;
        }
    }
    if(optind != argc - 2){
        printf("usage:%s [-n] <pathname> <type>\n",argv[0]);
        return 1;
    }

    int id = msgget(ftok(argv[optind],1),O_RDONLY);

    if(-1 == id){
        perror("msgget error");
        return 1;
    }
    size_t msglen = BUFSIZ;
    struct msgbuf* buf = malloc(sizeof(long)+msglen);
    
    if(-1 == msgrcv(id,buf,msglen,atoi(argv[optind+1]),flag)){
        perror("fcntl error");
        return 1;
    }
    printf("read:%s",buf->mtext);
}

消息控制:int msgctl(int msgqid,int cmd,struct msgqid_ds *buf);msgqid:消息隊(duì)列標(biāo)識(shí)符阿纤;IPC_STAT:獲取當(dāng)前消息隊(duì)列控制信息句灌;IPC_SET:設(shè)置當(dāng)前消息隊(duì)列控制信息;IPC_RMID:刪除消息隊(duì)列欠拾;buf:消息隊(duì)列的模式結(jié)構(gòu)涯塔,msg_perm.mode:表示消息隊(duì)列讀寫模式;msg_qbytes:隊(duì)列最大大星迨础匕荸;msg_cbytes:當(dāng)前隊(duì)列的大小枷邪;msg_qnum:表示當(dāng)前隊(duì)列的消息數(shù)榛搔;返回值:0表示成功,-1表示失敹А践惑;
msgctl.c:標(biāo)識(shí)用于刪除消息

#include <stdio.h>
#include <sys/msg.h>

int main(int argc,char* argv[]){
    int i;
    for(i=1;i<argc;i++){
        msgctl(atoi(argv[i]),IPC_RMID,NULL);
    }
}

對(duì)于消息隊(duì)列的查看可以使用ipcs來(lái)進(jìn)行查看;

System V 共享內(nèi)存

資料查看unpv22e嘶卧,ch14尔觉,頭文件sys/shm.h

相關(guān)的函數(shù)

共享內(nèi)存的獲取:int shmget(key_t key, size_t size, int shmflg)芥吟;key:命名共享內(nèi)存IPC_PRIVATE侦铜,key_t ftok(const char *fname,int fd)专甩;fname:標(biāo)識(shí)已經(jīng)存在的文件路徑,id:表示子序號(hào)1--255钉稍;size:表示內(nèi)存容量涤躲,非0表示新建的共享內(nèi)存大小,0表示獲取共享內(nèi)存指定為0贡未;shmflg:IPC_CREAT:用于創(chuàng)建共享內(nèi)存种樱;IPC_CREAT | IPC_EXCL;權(quán)限:建議使用八進(jìn)制數(shù)字來(lái)表示俊卤;返回值:非負(fù)整數(shù)嫩挤,表示共享內(nèi)存表示符,-1表示失斚小岂昭;
shmget.c:

#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>

int main(int argc,char* argv[]){
    key_t key = ftok(argv[1],1);
    if(-1 == key){
        perror("ftok err");
        return 1;
    }
    int shmid = shmget(key,atoi(argv[2]),IPC_CREAT|0644);
    if(-1 == shmid){
        perror("shmget err");
        return 1;
    }
    printf("shmid:%d\n",shmid);
    return 0;
}

共享內(nèi)存鏈接:void *shmat(int shmid,const void *shmaddr,int shmflg);shmid:共享內(nèi)存標(biāo)識(shí)符哺哼;shmaddr:指定共享內(nèi)存連接到當(dāng)前及才能拿中的地址位置;通常設(shè)置為NULL叼风,表示讓系統(tǒng)來(lái)選擇共享內(nèi)存的地址取董,這點(diǎn)是出于兼容性考慮;shmflg:表示標(biāo)志位无宿,SHM_RDONLY茵汰,只讀,0表示讀寫孽鸡;返回值:非負(fù)整數(shù)表示共享內(nèi)存指針蹂午,-1表示失敗彬碱;
shmread.c

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>

int main(int argc,char* argv[]){
    key_t key = ftok(argv[1],1);
    if(-1 == key){
        perror("ftok err");
        return 1;
    }
    int shmid = shmget(key,0,O_RDONLY);
    if(-1 == shmid){
        perror("shmget err");
        return 1;
    }
    void* buf = shmat(shmid,NULL,SHM_RDONLY);
    printf("%s\n",buf);
    shmdt(NULL);
    printf("shmid:%d\n",shmid);
    return 0;
}

共享內(nèi)存分離:int shmdt(const void *shmaddr)豆胸;shmaddr:表示共享內(nèi)存指針;返回值0表示成功巷疼,-1表示失斖砗;

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

共享內(nèi)存控制:int shmctl(int shmid,int cmd,struct shmid_ds *buf)嚼沿;shmid:共享內(nèi)存標(biāo)識(shí)符估盘;cmd:IPC_STAT,獲取當(dāng)前共享內(nèi)存控制信息骡尽;IPC_SET:設(shè)置當(dāng)前共享內(nèi)存控制信息遣妥;IPC_RMID:刪除共享內(nèi)存;buf:共享內(nèi)存信息結(jié)構(gòu):int shm_segsz攀细,表示共享內(nèi)存大小箫踩,shm_perm.mode:表示讀寫權(quán)限爱态;返回值:0表示成功,-1表示失敯嗵住肢藐;獲取共享內(nèi)存大小,shmctl(shmid,IPC_STAT,&buf)吱韭;buf.shm_segsz吆豹;刪除共享內(nèi)存:shmctl(shmid,IPC_RMID理盆,NULL)痘煤;
shmctl.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>

int main(int argc,char* argv[]){
    
    if(-1 == shmctl(atoi(argv[1]),IPC_RMID,NULL)){
        perror("shmctl err");
        return 1;
    }
}

共享內(nèi)存也可以使用ipcs進(jìn)行查看;

System V信號(hào)量

&38195;unpv22e猿规,ch11衷快;頭文件是:、sys/sem.h

相關(guān)函數(shù)

信號(hào)量的獲纫塘:int semget(key,nsems,semflg)蘸拔;key:表示命名信號(hào)量IPC_PRIVATE,key_t ftok(const char *fname,int fd)环葵;fname:已存在的文件路徑调窍;id:表示子序號(hào),1--255张遭;nsems:信號(hào)量數(shù)目邓萨,0表示獲取信號(hào)量指定為0,非0新建的信號(hào)量數(shù)量菊卷;semflag:IPC_CREAT缔恳,信號(hào)量已經(jīng)存在不出錯(cuò),IPC_CREAT | IPC_EXCL洁闰,信號(hào)量已存在出錯(cuò)歉甚,權(quán)限建議使用八進(jìn)制數(shù)字;返回值:非負(fù)整數(shù)扑眉,信號(hào)量標(biāo)識(shí)铃芦,-1表示失敗襟雷;
semcreate.c

#include <stdio.h>
#include <unistd.h>
#include <sys/sem.h>

int main(int argc,char* argv[]){
    key_t key = ftok(argv[1],1);
    if(-1 == semget(key,1,IPC_CREAT|0644)){
        perror("semget err");
        return 1;
    }
}

信號(hào)量操作:int semop(int semid,struct sembuf *sops,size_t nsops)刃滓;semid:表示信號(hào)量標(biāo)識(shí);sops:信號(hào)量結(jié)構(gòu)體耸弄,sem_num:信號(hào)量下標(biāo)咧虎,從0開(kāi)始,sem_flg:SEM_UNDO:表示在進(jìn)程結(jié)束時(shí)计呈,相應(yīng)的操作將會(huì)被取消砰诵,進(jìn)程沒(méi)有釋放該信號(hào)量而終止時(shí)操作系統(tǒng)釋放信號(hào)量征唬;0:表示的是默認(rèn)的選項(xiàng);IPC_NOWAIT:表示非阻塞狀態(tài)茁彭;sem_op:-1表示P操作总寒,1:表示V發(fā)送操作;nsops:semops大欣矸巍摄闸;
race.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/sem.h>
#include <unistd.h>

void sem_p(int semid){
    struct sembuf buf;
    buf.sem_num = 0;
    buf.sem_op = -1;
    buf.sem_flg = 0;
    semop(semid,&buf,1);
}
void sem_v(int semid){
    struct sembuf buf;
    buf.sem_num = 0;
    buf.sem_op = 1;
    buf.sem_flg = 0;
    semop(semid,&buf,1);
}

union semun{
    int val;
};

int main(int argc,char * argv[]){
    int semid  = semget(IPC_PRIVATE,1,IPC_CREAT|0644);
    union semun un = {1};
    if(-1 == semctl(semid,0,SETVAL,un)){
        perror("semctl err");
        return 1;
    }
    if(-1 == semid){
        perror("semget err");
        return 1;
    }

    fork();
    int i=0;
    for(;i<5;i++){
        sem_p(semid);
        printf("PID:%d,enter\n",getpid());
        sleep(1);
        printf("PID:%d,do something\n",getpid());
        printf("PID:%d,leave\n",getpid());
        sem_v(semid);
    }
}

信號(hào)量控制:int semctl(semid, nsem,cmd,...);semid:信號(hào)量標(biāo)識(shí)妹萨;nsem:信號(hào)量下標(biāo)年枕;cmd:SETVAL,用于設(shè)置信號(hào)量的值乎完;GETVAL熏兄,獲取信號(hào)量的值;IPC_RMID树姨,表示刪除信號(hào)量的值摩桶;...:union semnum;
設(shè)置信號(hào)量的初始值semctl(smeid,信號(hào)量下標(biāo),SETVAL帽揪,semnum)硝清;

union semun {
          int val;
          struct semid_ds *buf;
          unsigned   short  *arry;
};

刪除信號(hào)量:semctl(semid,信號(hào)量下標(biāo)台丛,IPC_RMID)耍缴;
semrmid.c

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/sem.h>

int main(int argc,char* argv[]){
    key_t key = ftok(argv[1],1);
    int semid;
    if((semid = semget(key,0,O_RDWR))==-1){
        perror("semget err");
        return 1;
    }
    if(-1 == semctl(semid,0,IPC_RMID)){
        perror("semctl err");
        return 1;
    }
}

查看使用ipcs命令砾肺;
需要注意的幾點(diǎn)是:
1挽霉、ftok()首個(gè)參數(shù)必須是已存在的路徑名;
2变汪、使用XXget()創(chuàng)建時(shí)侠坎,必須是使用IPC_CREAT,而不是O_CREAT
3裙盾、讀寫非阻塞的操作必須是設(shè)置在open打開(kāi)的操作中实胸;
Posix:優(yōu)先級(jí)高的先出;
System V:當(dāng)mtype小于0時(shí)番官,小于mtype絕對(duì)值的消息中庐完,最小的先出;0最先進(jìn)入的先出徘熔;>0

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末门躯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子酷师,更是在濱河造成了極大的恐慌讶凉,老刑警劉巖染乌,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異懂讯,居然都是意外死亡荷憋,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門褐望,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)勒庄,“玉大人,你說(shuō)我怎么就攤上這事譬挚」Γ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵减宣,是天一觀的道長(zhǎng)盐须。 經(jīng)常有香客問(wèn)我,道長(zhǎng)漆腌,這世上最難降的妖魔是什么贼邓? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮闷尿,結(jié)果婚禮上塑径,老公的妹妹穿的比我還像新娘。我一直安慰自己填具,他們只是感情好统舀,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著劳景,像睡著了一般誉简。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上盟广,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天闷串,我揣著相機(jī)與錄音,去河邊找鬼筋量。 笑死烹吵,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的桨武。 我是一名探鬼主播肋拔,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼呀酸!你這毒婦竟也來(lái)了凉蜂?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎跃惫,沒(méi)想到半個(gè)月后叮叹,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡爆存,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年蛉顽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片先较。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡携冤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出闲勺,到底是詐尸還是另有隱情曾棕,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布菜循,位于F島的核電站翘地,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏癌幕。R本人自食惡果不足惜衙耕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望勺远。 院中可真熱鬧橙喘,春花似錦、人聲如沸胶逢。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)初坠。三九已至和簸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間某筐,已是汗流浹背比搭。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工冠跷, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留南誊,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓蜜托,卻偏偏與公主長(zhǎng)得像抄囚,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子橄务,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 進(jìn)程間的通信主要分為本機(jī)器進(jìn)程間的通信和不同機(jī)器間進(jìn)程的通信幔托。本文主要描述本機(jī)進(jìn)程間的通信。 一、傳統(tǒng)Linux的...
    一葉之界閱讀 398評(píng)論 0 2
  • 儒家與鬼神 大拙 《論語(yǔ)·述而》有云: “子不語(yǔ)怪力亂神重挑∩せ”一般都理解為“孔子不談?wù)摴之悺⒂铝γА⑴褋y和鬼...
    豬大拙閱讀 1,382評(píng)論 0 1
  • 想得到的刺覆,需要付出努力,但最終不一定得到史煎。
    七根白發(fā)閱讀 119評(píng)論 0 0
  • 你是否遇到過(guò)這樣的困擾: 當(dāng)你寫完一段代碼后谦屑,要看到效果,必須點(diǎn)擊IDEA的停止按鈕篇梭,然后再次重啟啟動(dòng)項(xiàng)目氢橙,你是否...
    周小春閱讀 4,435評(píng)論 0 7
  • 美好晨光,有媽媽恬偷,有孩子悍手,有一份工作
    其其菱菱閱讀 117評(píng)論 0 0