• 【C语言_文件_进程_进程间通讯 常用函数/命令 + 实例】.md_update:23/10/27


    文件相关命令

    ps -aux|grep init?      //搜索包含init名称的进程
    top                     //linux下的资源管理器(动态)
    
    //open 返回的int 是给后面的读/写/光标移动 用的fd,没有open就不能进行后面的操作;
    int open(const char *pathname, int flags);
    int open(const char *pathname, int flags, mode_t mode);
    close(fd); //关闭文件
    
    // _t 都是返回的int数字;写write,读read,光标移动lseek
    ssize_t write(int fd, const void *buf, size_t count);
    ssize_t read(int fd, void *buf, size_t count);
    
    vimdiff demo1.c demo2.c 
    
    //fopen注意mode就行,有:r r+ w w+ a ,返回的文件指针是给后面的读 写 偏移用
    FILE *fopen(const char *pathname, const char *mode);
    fclose(FILE *); //关闭文件
    
    //跟上面的差不多一样用
    //fread/fwrite(读写的数组,读写的大小,  读写的最大次数?, 读写的文件指针)
                    (读写返回次数的区别:读为有效次数,能一次读完就算你写10次,也返回只读1次)
    size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
    size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
    int fseek(FILE *stream, long offset, int whence);
    
    fputc();//写入一个字符;
    fgetc();//读取一个字符
    feof();/检测是否到达文件末尾,到了返回1;文件结束符为EOF=-1;
    
    //注意:读写操作都会使光标偏移,但也可以利用这点来遍历读写文件;
    例:
    while(!feof(FILE* fd)){
            printf("%c  ",fgetc(FILE* fd));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    进程相关命令

    getpid(); fork(); vfork();

    //_t 一律返回的是int
    //获取进程ID 就是pid
    pid_t getpid(void);

    //fork创建子进程
    pid_t fork(void);
    //这里返回的是的pid = 0 就是子进程,pid > 0 就是父进程;
    //所以可以通过判断pid的值,来区别父子进程需要执行的代码;
    //注意fork开辟的子进程,没有等待一说,父子进程谁抢到就先运行谁,
    //【子进程为僵尸进程】;
    //例:

        #include
        #include 
        #include 
        #include 
        int main()
        {
                pid_t pid;
    
                int num = 0;
                pid = getpid();
                printf("this pid:%d\n",getpid());
    
    
                pid_t return_pid = fork();
    
                if(return_pid > 0){
                        while(1){
                        printf("this father pid:%d return_pid:%d \n",getpid(),return_pid);
                        printf("father now num:%d\n",num);
                        sleep(1);
                        }
    
                }else if(return_pid == 0){
    
                        printf("this son pid:%d return_pid:%d \n",getpid(),return_pid);
                        num += 2;
                        printf("child now num:%d\n",num);
                        exit(6);
                }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    //vfork创建子进程
    pid_t vfork(void);
    //注意fork开辟的子进程,会等待子进程执行完并exit(num)后,父子进程才继续执行,
    //【子进程不会成为僵尸进程】;
    //例:

        #include
        #include 
        #include 
        #include 
        int main()
        {
                pid_t pid;
                pid = getpid();
                printf("this pid:%d\n",getpid());
                int num = 0;
                printf("start_father_num:%d \n",num);
                pid_t return_pid = vfork();
                if(return_pid > 0){
                        while(1){
                                printf("this father pid:%d return_pid:%d \n",getpid(),return_pid);
                                printf("num = %d\n",num);
                                sleep(1);
                        }
                }
                else if(return_pid == 0){
                        int i;
                        for(i=0;i<3;i++){
                                printf("this son pid:%d return_pid:%d \n",getpid(),return_pid);
                                num++;
                                sleep(1);
                        }
                        exit(0);
                }
                return 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    exit(6);wait(status); WEXITSTATUS(status);

    //wait() 返回的是子进程的ID 即pid;
    //里面的 int *status 是子进程的exit(num)的num码;
    //后续使用WEXITSTATUS(status),即可打印出来子进程退出时的状态码
    pid_t wait(int *status);
    //例:

        #include 
        #include 
        #include 
        #include 
        int main()
        {
                pid_t pid;
                int status = 0;
                pid = getpid();
                printf("start father pid:%d\n",getpid());
                pid_t return_pid = fork();
                if(return_pid > 0 ){
                        pid_t child_pid = wait(&status);
                        printf("\n\nwait_return_childe_pid:%d\n",child_pid);
                        printf("child exit code:%d \n",WEXITSTATUS(status));
                        while(1){
                        printf("this father pid:%d fork_return_pid:%d > 0  \n",getpid(),return_pid);
                        sleep(1);
                        }
                        }else if(return_pid == 0){
                                int i;
                                for(i=0;i<3;i++){
                                        printf("this son pid:%d fork_return_pid:%d == 0 \n",getpid(),return_pid);
                                }
                                exit (6);
                        }
    
    
    
                return 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    exec组函数 对比 system + popen :

    精彩博文参照:
    https://blog.csdn.net/u014530704/article/details/73848573

    观后感:

    跟着execl/execlp指定的程序跑了,不回来了!

    //  date 获取时间的程序
    execl("./PATH","date","NULL");
    //  execl(程序所在路径,程序名,结尾必须为NULL)
    //  就像这样用,在当前程序运行到这句代码时,
    //  便将替换为后续执行execl所指的程序,不带回头的那种!
    
    execlp("date","date",NULL);
    //  execlp(程序名,程序名,结尾必须为NULL)
    //  就像这样用,它带p,能自己在环境变量下搜索对应的程序并替换后续执行;
    //  也是不带回头的那种!
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    相比较之下 system 执行完指定程序后,还会回来,挺好!

    system("cat demo1.c");
    //执行完成后返回原程序,继续执行后续代码;
    
    • 1
    • 2

    而对比popen 而言,popen除了将指定程序/代码执行完之后,继续执行后续代码外,还将读/写的内容放在管道内,并以文件指针的形式返回;

        #include 
        #include 
        int main()
        {
                printf("------------------------------------------------\nPS:\n");
    
                char* p = "ps";
                FILE *fd = popen(p,"r");
                char data[1024];
                fread(&data,1024,1,fd);
                printf("%s\n",data);
                perror("why");
                return 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    进程间通讯

    精彩博文参照
    http://t.csdnimg.cn/xN2LT

    观后感:

    pipe 无名管道

    int pipe(int pipefd[2]); (无名管道,在文件里看不到)

    里面的fd[2]数组,其中 fd[0] : 读的fd, fd[1] : 写的fd;

    //例:通过在父子进程中 close (fd[0]/fd[1]) 配合read(); write(); 实现进程间通讯;

    #include 
    #include 
    #include 
    #include 
    int main()
    {
            printf("------------------------------------------------:\n");
            int fd[2];
            int n_pipe = pipe(fd);
    
            char data1[128];
            if(n_pipe < 0){
                    printf("error: can not creat pipe!\n");
                    perror("why");
            }
    
            int pid = fork();
            if(pid < 0){
                    printf("error: creat child failed!\n");
                    perror("why");
            }
            if(pid > 0){
                    // sleep(2);
                    printf("this is father pc\n");
                    close(fd[0]);
                    write(fd[1],"hello pipe from father;",strlen("hello pipe from father;"));
                    close(fd[1]);
            }
            if(pid == 0){
                    printf("this is child pc\n");
                    close(fd[1]);
                    read(fd[0],data1,128);
                    printf("data : %s\n",data1);
                    exit(9);
                    }
            return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    mkfifo 有名管道

    //成功返回0;失败返回-1 设置erron = -1;
    //返回值判断报错值:EEXIST,可以锁定报错为同名文件已存在目录中;
    int mkfifo(const char *pathname, mode_t mode);
    RETURN VALUE
    On success mkfifo() and mkfifoat() return 0. In the case of
    an error, -1 is returned (in which case, errno is set appro‐
    priately).
    EEXIST pathname already exists. This includes the case where
    pathname is a symbolic link, dangling or not.

    //例:

        #include
        #include 
        #include 
        #include 
        int main()
        {
                if(mkfifo("./demo1.txt",0666) < 0 && errno == EEXIST ){
                printf("mkfifo error:\n");
                perror("why");
        }
        return 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    //mkfifo 配合 open read write 完成管道通讯;
    //demo mkread:

        #include
        #include 
        #include 
        #include 
        #include 
        #include 
        #include 
        int main()
        {
                char buf[30]={0};
                int nff = mkfifo("./demo10.txt",0600);
                if(nff < 0 || errno == EEXIST ){
                        printf("mkfifo error:\n");
                        perror("why");
                }
                if(nff == 0){
                        printf("mkfifo OK! \n");
                }
                int fd = open("./demo10.txt",O_RDONLY);
                printf("open success\n");
    
                int n_read = read(fd,buf,30);
                printf("read %d byte frome fifo context:\n%s\n",n_read,buf);
    
                int n_sys = system("rm ./demo10.txt");
                if(n_sys < 0 || n_sys ==127 ){
                        printf("./demo10.txt delect error! \n");
                        perror("why");
                }else{
                        printf("\n--------------------------------------------");
                        printf("\nsystem: ./demo10.txt delect success !\n");
                        printf("--------------------------------------------\n");
    
                }
    
                close(fd);
                return 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    //demo mkwrite:

        #include
        #include 
        #include 
        #include 
        #include 
        #include 
        #include 
        int main()
        {
                char buf[30]={"hello mkfifo file_read/write"};
    
                int fd = open("./demo10.txt",O_WRONLY);
                printf("open success\n");
    
                int n_write = write(fd,buf,strlen(buf));
                printf("write %d byte frome fifo context:\n%s\n",n_write,buf);
    
                close(fd);
                return 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    消息队列

    // 生成标准key 给后面msgget用;
    // key_t ftok(const char *pathname, int proj_id);

    // 获取msgid;
    // int msgget(key_t key, int msgflg);

    // 添加消息
    // int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

    // 读取消息
    // ssize_t msgrcv(int msqid, const void *msgp, size_t msgsz,long msgtyp, int msgflg);

    // 控制消息队列 比如:杀掉消息队列
    // int msgctl(int msqid, int cmd, struct msqid_ds *buf);

    //杀掉消息队列 配合实现: msgctl(n_msgget,IPC_RMID,NULL);
    // IPC_RMID

    //例a:ftok_msgget_msgsnd_msgctl.c

        #include 
        #include 
        #include 
        #include 
        #include 
    
        struct NB {
                long msgtyp;
                char data[30];
        };
    
        int main()
        {
                struct NB ZDNB ={998,"Are you ok?"};
                printf("%ld\n",ZDNB.msgtyp);
    
                //key_t ftok(const char *pathname, int proj_id);        
                int key = ftok(".",6);
    
                printf("key = %x\n",key);
    
                //int msgget(key_t key, int msgflg);
                int n_get =  msgget(key, IPC_CREAT|0777);
                if(n_get >= 0){
                        printf("msgget succes code:%d\n",n_get);
                        perror("why");
                }else{
                        printf("msgget error! code:%d\n",n_get);
                        perror("why");
                }
    
                //int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
                int snd = msgsnd(n_get,&ZDNB,sizeof(ZDNB.data),0);
                printf("msgsnd code:%d\n",snd);
                perror("why");
    
                struct NB ZDNB1;
                //ssize_t msgrcv(int msqid, const void *msgp, size_t msgsz,long msgtyp, int msgflg);
                int rcv = msgrcv(n_get,&ZDNB1,sizeof(ZDNB1.data),888,0);
                printf("msgrcv read code:%d\n",rcv);
                printf("--------------------------------------------\n");
                printf("read frome ./rcv_888 massege is:\n%s\n",ZDNB1.data);
                printf("--------------------------------------------\n");
    
                //int msgctl(int msqid, int cmd, struct msqid_ds *buf);
                int ctl = msgctl(n_get,IPC_RMID,NULL);
                printf("msgctl code:%d\n",ctl);
                perror("why");
                return 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    //例b:msgrcv.c

        #include
        #include 
        #include 
        #include 
        #include 
        #include 
        struct NB {
                long msgtyp;
                char data[30];
        };
    
        int main()
        {
                struct NB ZNB1 ={888,"I am ok,Thank you!"};
                printf("%ld\n",ZNB1.msgtyp);
                struct NB ZNB;
                //key_t ftok(const char *pathname, int proj_id);        
                int key = ftok(".",6);
                printf("key = %x\n",key);
    
                //int msgget(key_t key, int msgflg);
                printf("key = %x\n",key);
    
                //int msgget(key_t key, int msgflg);
                int n_get =  msgget(key, IPC_CREAT|0777);
                if(n_get >= 0){
                        printf("msgget succes code:%d\n",n_get);
                        perror("why");
                }else{
                        printf("msgget error! code:%d\n",n_get);
                        perror("why");
                }
    
                //ssize_t msgrcv(int msqid, const void *msgp, size_t msgsz,long msgtyp, int msgflg);
                int rcv = msgrcv(n_get,&ZNB,sizeof(ZNB.data),998,0);
                printf("msgrcv read code:%d\n",rcv);
                printf("--------------------------------------------\n");
                printf("read frome ./snd_998 massege is:\n%s\n",ZNB.data);
                printf("--------------------------------------------\n");
    
                //int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
                int snd = msgsnd(n_get,&ZNB1,sizeof(ZNB1.data),0);
                printf("msgsnd code:%d\n",snd);
                perror("why");
    
                sleep(1);
                //int msgctl(int msqid, int cmd, struct msqid_ds *buf);
                int ctl = msgctl(n_get,IPC_RMID,NULL);
                printf("msgctl code:%d\n",ctl);
                perror("why");
                return 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    共享内存_映射

    // 生成标准key给shmget用;
    // key_t ftok(const char *pathname, int proj_id);

    // 生成共享内存ID;
    // int shmget(key_t key, size_t size, int shmflg);

    // 创建映射;通过共享内存ID; shmaddr 写 0;shmflg 写0;–均代表默认方式;
    // void *shmat(int shmid, const void *shmaddr, int shmflg);
    // int shmdt(const void *shmaddr); (不常用,因为没返回映射指针)

    // 关闭映射;
    // int shmdt(const void *shmaddr);

    // 使用strcpy();写入映射;
    // char *strcpy(char *dest, const char *src);
    // char *strncpy(char *dest, const char *src, size_t n);

    //printf(“”,);
    // 查看当前共享内存映射
    // ipcs -m;

    // 杀掉共享内存映射ID;
    // ipcrm -m shmID;

    // 通过内存ID,删除共享文件的内存
    // shmctl(shmid,IPC_RMID,0);

    //例:shm_strcpy:

        #include 
        #include 
        #include 
        #include 
        #include 
        #include 
        int main()
        {
    
                int key = ftok(".",3);
                int shmid = shmget(key,1024*4,IPC_CREAT|0777);
                if(shmid < 0){
                        printf("shmid error ! code:%d\n",shmid);
                        perror("why");
                }
                char *shmaddr = shmat(shmid,0,0);
    
                char *cpy = strcpy(shmaddr,"hello shm friends!");
                printf("strcpy data to shm:\n%s\n",cpy);
                sleep(5);
    
                int dt = shmdt(shmaddr);
                if(dt >= 0){
                        printf("shmdt code:%d\n",dt);
                        perror("why");
                }
    
                shmctl(shmid,IPC_RMID,0);
                printf("quite\n");
                return 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    //例:shm_printf:

        #include 
        #include 
        #include 
        #include 
        #include 
        #include 
        int main()
        {
    
                int key = ftok(".",3);
                int shmid = shmget(key,1024*4,0);
                if(shmid < 0){
                        printf("shmid error ! code:%d\n",shmid);
                        perror("why");
                }
                char *shmaddr = shmat(shmid,0,0);
                printf("from shm data:\n%s\n",shmaddr);
                int dt = shmdt(shmaddr);
                if(dt > 0){
                        printf("shmdt code:%d\n",dt);
                        perror("why");
                }else{
                        perror("why");
                }
                shmctl(shmid,IPC_RMID,0);
                printf("quite\n");
                return 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    信号编程

    查看信号: kill -l

    在这里插入图片描述

    入门级 接收消息 signal signum

    //sighandler_t signal(int signum, sighandler_t handler);
    DESCRIPTION
    signal() sets the disposition of the signal
    signum to handler,
    The signals SIGKILL and SIGSTOP cannot be caught
    or ignored.

    //例:

        #include 
        #include 
        void handler(int signum)
        {
                printf("signum:%d\n",signum);
                switch(signum){
                        case 2:
                                printf("SIGINT\n");
                                break;
                        case 9:
                                printf("SIGKILL\n");
                                break;
                }
        }
        int main()
        {
                
                signal(SIGINT,handler);
                signal(SIGKILL,handler);
                while(1);
                return 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    入门级 发送信号 实现杀进程 kill -9 pid

    //例:

        #include 
        #include 
        #include 
    
        int main(int argc,char **argv)
        {
                int num = atoi(argv[1]);
                int pid = atoi(argv[2]);
                char buf[30] = {0};
    
                sprintf(buf,"kill %d %d",num,pid);
                system(buf);
    
                return 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    高级 sigaction 接受信号_携带消息
        #include 
        #include 
        #include 
        #include 
    
        //void handler(int sig, siginfo_t *info, void *ucontext)
        void handler(int signum, siginfo_t *info, void *ucontext)
        {
                printf("get signum:%d\n",signum);
                if(ucontext != NULL){
                        printf("get data:%d\n",info->si_int);
                        printf("get data:%d\n",info->si_value.sival_int);
                        printf("frome pid:%d\n",info->si_pid);
                }
        }
    
        int main()
        {
                /*
                struct sigaction {
                void     (*sa_handler)(int);
                void     (*sa_sigaction)(int, siginfo_t *, void *); //if sa_flags = SA_SIGINFO, setthere it is handler;
                sigset_t   sa_mask;
                int        sa_flags; //SA_SIGINFO able get sig;
                void     (*sa_restorer)(void);
                };
                */
    
                struct sigaction act;
    
                act.sa_flags = SA_SIGINFO;
                act.sa_sigaction = handler;
    
                printf("getpid:%d\n",getpid());
                //int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
    
                sigaction(SIGUSR1,&act,NULL);
    
                while(1);
                return 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    高级 sigqueue 发送信号_携带消息
        #include 
        #include 
        #include 
        #include 
        #include 
    
        int main(int argc,char** argv)
        {
    
                //moren have 
    
                /*
                union sigval {
                int   sival_int;
                void *sival_ptr;
                };
                */
    
                int pid = atoi(argv[2]);
                int signum = atoi(argv[1]);
                union sigval value;
                value.sival_int = 666;
    
                printf("getpid:%d\n",getpid());
                //int  sigqueue(pid_t  pid, int signum, const union sigval value);
                int que = sigqueue(pid,signum,value);
                if(que >= 0){
                        printf("send int data success!\n");
                }else{
                        perror("why");
                }
                return 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    信号量编程

    信号量(semaphore)与IPC 结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。

    信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
    信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作。
    每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数。
    支持信号量组。

    //例:通过信号量+/-1,实现父子进程,执行顺序控制;

    #include 
    #include 
    #include 
    #include 
    #include 
    
    union semun {
        int              val;    /* Value for SETVAL */
        struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
        unsigned short  *array;  /* Array for GETALL, SETALL */
        struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                    (Linux-specific) */
    };
    
    // EXAMPLE
    // The following code segment uses semop() to atomically wait  for  the
    // value  of  semaphore  0 to become zero, and then increment the sema‐
    // phore value by one.
    
    //     struct sembuf sops[2];
    //     int semid;
    
    //     /* Code to set semid omitted */
    
    //     sops[0].sem_num = 0;        /* Operate on semaphore 0 */
    //     sops[0].sem_op = 0;         /* Wait for value to equal 0 */
    //     sops[0].sem_flg = 0;
    
    //     sops[1].sem_num = 0;        /* Operate on semaphore 0 */
    //     sops[1].sem_op = 1;         /* Increment value by one */
    //     sops[1].sem_flg = 0;
    
    //     if (semop(semid, sops, 2) == -1) {
    //         perror("semop");
    //         exit(EXIT_FAILURE);
    //     }
    
    void pGetKey( int semid) //拿锁/信号量
    {
        struct sembuf set;
        //int semop(int semid, struct sembuf *sops, size_t nsops);
        set.sem_num = 0;        /* Operate on semaphore 0 */
        set.sem_op = -1;         //对信号量的值-1,拿掉一个锁;
        set.sem_flg = SEM_UNDO;  //在进程终止时自动释放所持有的信号量资源
                                     //释放/公布盒子位置;
        semop(semid, &set, 1);
    
        printf("get_key sem success!\n");
    }
    
    void vPutBackKey( int semid) //还锁/信号量
    {
        struct sembuf set;
        //int semop(int semid, struct sembuf *sops, size_t nsops);
        set.sem_num = 0;        /* Operate on semaphore 0 */
        set.sem_op = 1;         //对信号量的值+1,还一个锁;
        set.sem_flg = SEM_UNDO;  //在进程终止时自动释放所持有的信号量资源
                                     //释放/公布盒子位置;
        
        semop(semid, &set, 1);
    
        printf("back_key sem success!\n\n");
    }
    
    int main()
    {
        int key = ftok(".",2);
        //int semget(key_t  key,nsems, int semflg);
        //获取/创建 1个信号量/1个盒子;
        int semid = semget (key,1,IPC_CREAT|0666);
        
        union semun initsem;
        initsem.val = 0; //起始信号量的值位0;盒子0个锁;
    
        //int semctl(int semid, int semnum, int cmd, ...);
        //如果要SETVAL设置信号量的值,需要多加个联合体变量initsem;
        semctl(semid,0,SETVAL,initsem);
    
        int pid = fork();
        if(pid > 0){
            //去拿锁,但一开始盒子里没有锁,所以就先执行子进程放锁;
            pGetKey(semid); 
            printf("is father pid:%d\n",pid);
            //用完了,再把锁放回盒子;
            vPutBackKey(semid);
    
            //不需要设值,则3个变量即可,关掉信号量;
            semctl(semid,0,IPC_RMID);
        }else if(pid == 0){
            printf("is child pid:%d\n",pid);
            //子进程放锁进去;
            vPutBackKey(semid);        
        }else{
            printf("fork error! code:%d\n",pid);
            perror("why");
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    信号量+共享内存 实现进程通讯
    //例:(双信号量实现)

    //双信号量发送端:

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    union semun {
            int              val;    /* Value for SETVAL */
            struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
            unsigned short  *array;  /* Array for GETALL, SETALL */
            struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                        (Linux-specific) */
    };
    
    void pGetKey( int semid,int num) //拿锁/信号量
    {
            struct sembuf set;
            //int semop(int semid, struct sembuf *sops, size_t nsops);
            set.sem_num = num;        /* Operate on semaphore 0 */
            set.sem_op = -1;         //对信号量的值-1,拿掉一个锁;
            set.sem_flg = SEM_UNDO;  //在进程终止时自动释放所持有的信号量
    资源
            //释放/公布盒子位置;
            semop(semid, &set, 1);
            printf("get_key sem success!\n");
    }
    
    void vPutBackKey( int semid,int num) //还锁/信号量
    {
            struct sembuf set;
            //int semop(int semid, struct sembuf *sops, size_t nsops);
            set.sem_num = num;        /* Operate on semaphore 0 */
            set.sem_op = 1;         //对信号量的值+1,还一个锁;
            set.sem_flg = SEM_UNDO;  //在进程终止时自动释放所持有的信号量
    资源
            //释放/公布盒子位置;
            semop(semid, &set, 1);
            printf("back_key sem success!\n\n");
    }
    int main()
    {
            //shmget use key
            int key = ftok(".",3);
            int shmid = shmget(key,1024*4,IPC_CREAT|0777);
    
            //semget use key2
            int key2 = ftok(".",2);
            //int semget(key_t  key,nsems, int semflg);
            //获取/创建 2个信号量;
            //control控制 rd_wr
            int semid = semget (key2,2,IPC_CREAT|0666);
            //semid是信号集id;
    
            union semun initsem;
            union semun initsem2;
            initsem.val = 1; //信号量1的值1;1个锁;
            initsem2.val = 0;//信号量2的值0;0个锁;
    
            //int semctl(int semid, int semnum, int cmd, ...);
            //如果要SETVAL设置信号量的值,需要多加个联合体变量initsem;
            //initsem no.0 
            semctl(semid,0,SETVAL,initsem);
            semctl(semid,1,SETVAL,initsem2);
    
            pGetKey(semid,0);
            if(shmid < 0){
                    printf("shmid error ! code:%d\n",shmid);
                    perror("why");
            }
            char *shmaddr = shmat(shmid,0,0);
    
            char *cpy = strcpy(shmaddr,"hello _sem_shm friends!");
            printf("snd data:\n%s\n",cpy);
    
            int dt = shmdt(shmaddr);
            if(dt >= 0){
                    printf("shmdt code:%d\n",dt);
                    perror("why");
            }
            vPutBackKey(semid,1);
    
            shmctl(shmid,IPC_RMID,0);
            semctl(semid,0,IPC_RMID);
            semctl(semid,1,IPC_RMID);
    
            printf("quite\n");
            return 0;
    }        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90

    //双信号量接收端:

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    union semun {
            int              val;    /* Value for SETVAL */
            struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
            unsigned short  *array;  /* Array for GETALL, SETALL */
            struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                        (Linux-specific) */
    };
    
    void pGetKey( int semid,int num) //拿锁/信号量
    {
            struct sembuf set;
            //int semop(int semid, struct sembuf *sops, size_t nsops);
            set.sem_num = num;        /* Operate on semaphore 0 */
            set.sem_op = -1;         //对信号量的值-1,拿掉一个锁;
            set.sem_flg = SEM_UNDO;  //在进程终止时自动释放所持有的信号量
    资源
            //释放/公布盒子位置;
            semop(semid, &set, 1);
            printf("get_key sem success!\n");
    }
    
    void vPutBackKey( int semid,int num) //还锁/信号量
    {
            struct sembuf set;
            //int semop(int semid, struct sembuf *sops, size_t nsops);
            set.sem_num = num;        /* Operate on semaphore 0 */
            set.sem_op = 1;         //对信号量的值+1,还一个锁;
            set.sem_flg = SEM_UNDO;  //在进程终止时自动释放所持有的信号量
    资源
            //释放/公布盒子位置;
            semop(semid, &set, 1);
            printf("back_key sem success!\n\n");
    }
    int main()
    {
            //shmget use key
            int key = ftok(".",3);
            int shmid = shmget(key,1024*4,IPC_CREAT|0777);
    
            //semget use key2
            int key2 = ftok(".",2);
            //int semget(key_t  key,nsems, int semflg);
            //获取/创建 2个信号量;
            //control控制 rd_wr
            int semid = semget (key2,2,IPC_CREAT|0666);
            //semid是信号集id;
    
            union semun initsem;
            union semun initsem2;
            initsem.val = 1; //信号量1的值1;1个锁;
            initsem2.val = 0;//信号量2的值0;0个锁;
    
            //int semctl(int semid, int semnum, int cmd, ...);
            //如果要SETVAL设置信号量的值,需要多加个联合体变量initsem;
            //initsem no.0 
            semctl(semid,0,SETVAL,initsem);
            semctl(semid,1,SETVAL,initsem2);
    
            pGetKey(semid,1);
            char *shmaddr = shmat(shmid,0,0);
    
            printf("from shm data:\n%s\n",shmaddr);
    
            int dt = shmdt(shmaddr);
            if(dt > 0){
                    printf("shmdt code:%d\n",dt);
                    perror("why");
            }else{
                    perror("why");
            }
            vPutBackKey(semid,0);
    
            printf("quite\n");
            return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    //例:(单信号量实现)

    //单信号量发送端:

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define KEY 1234
    
    // 定义共享内存结构
    struct shared_memory {
        int data;
    };
    
    // 定义信号量操作结构
    struct sembuf sem_op;
    
    int main() {
        int shm_id, sem_id;
        struct shared_memory *shm_ptr;
    
        // 创建共享内存
        shm_id = shmget(KEY, sizeof(struct shared_memory), IPC_CREAT | 0666);
        if (shm_id == -1) {
            perror("shmget");
            exit(1);
        }
    
        // 连接共享内存
        shm_ptr = (struct shared_memory *)shmat(shm_id, NULL, 0);
        if (shm_ptr == (struct shared_memory *)(-1)) {
            perror("shmat");
            exit(1);
        }
    
        // 创建信号量
        sem_id = semget(KEY, 1, IPC_CREAT | 0666);
        if (sem_id == -1) {
            perror("semget");
            exit(1);
        }
    
        // 初始化信号量
        semctl(sem_id, 0, SETVAL, 1);
    
        // 写入数据到共享内存
        shm_ptr->data = 42;
    
        // 通过信号量控制读进程的访问
        sem_op.sem_num = 0;
        sem_op.sem_op = 1;  // 增加信号量值
        sem_op.sem_flg = 0;
        semop(sem_id, &sem_op, 1);
    
        // 分离共享内存
        shmdt(shm_ptr);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    //单信号量发送端:

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define KEY 1234
    
    // 定义共享内存结构
    struct shared_memory {
        int data;
    };
    
    // 定义信号量操作结构
    struct sembuf sem_op;
    
    int main() {
        int shm_id, sem_id;
        struct shared_memory *shm_ptr;
    
        // 创建共享内存
        shm_id = shmget(KEY, sizeof(struct shared_memory), IPC_CREAT | 0666);
        if (shm_id == -1) {
            perror("shmget");
            exit(1);
        }
    
        // 连接共享内存
        shm_ptr = (struct shared_memory *)shmat(shm_id, NULL, 0);
        if (shm_ptr == (struct shared_memory *)(-1)) {
            perror("shmat");
            exit(1);
        }
    
        // 创建信号量
        sem_id = semget(KEY, 1, IPC_CREAT | 0666);
        if (sem_id == -1) {
            perror("semget");
            exit(1);
        }
    
        // 通过信号量等待写进程完成写入
        sem_op.sem_num = 0;
        sem_op.sem_op = -1;  // 减少信号量值
        sem_op.sem_flg = 0;
        semop(sem_id, &sem_op, 1);
    
        // 读取共享内存中的数据
        printf("Data read from shared memory: %d\n", shm_ptr->data);
    
        // 分离共享内存
        shmdt(shm_ptr);
    
        // 删除共享内存和信号量
        shmctl(shm_id, IPC_RMID, NULL);
        semctl(sem_id, 0, IPC_RMID);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    更新日志

    23/10/27:
    	使用markdown编写.md格式,增加目录,
    	更新内容:
    	a.信号量;
    	b.信号量+共享内存实现进程通讯;
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    Vue3打包后页面空白解决办法
    不会就坚持41天吧 最底最左值(二叉树)
    PMI-ACP练习题(26)
    openGauss学习笔记-119 openGauss 数据库管理-设置数据库审计-设置文件权限安全策略
    分页机制详解
    React原理(一)VirtualDom 到渲染UI
    spring自定义属性编辑器
    【动手学深度学习】--语言模型
    PHP 反序列化漏洞:身份标识
    openstack 业务组件安装
  • 原文地址:https://blog.csdn.net/Wdf_123654/article/details/134071780