1|进程管理 linux l例子

案例1:使用pipe()实现父子进程间通信,要求父进程作为写端,子进程作为读端。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
    int fd[2];//定义文件描述符数组
    int ret=pipe(fd);//创建管道
    if(ret==-1)
    {   
        perror("pipe");
        exit(1);
    }   
    pid_t pid=fork();
    if(pid>0)
    {   
        close(fd[0]);
        char *p="hello,pipe\n";
        write(fd[1],p,strlen(p)+1);
        close(fd[1]);
        wait(NULL);
    }
    else if(pid==0)
    {
        close(fd[1]);
        char buf[64]={0};
        ret=read(fd[0],buf,sizeof(buf));
        close(fd[0]);
        write(STDOUT_FILENO,buf,ret);
    }
    return 0;
}

案例2:使用管道实现兄弟进程间通信,使兄弟进程实现命令“ls | wc –l”的功能。在实现本案例时会用到重定向函数dup2(),该函数存在于函数库unistd.h中,函数声明如下:
int dup2(int oldfd, int newfd);
其功能是将参数oldfd的文件描述符复制给newfd,若函数调用成功则返回newfd,否则返回-1,并设置errno。
案例实现如下:

 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 int main()
 {
     int fd[2];
     int ret=pipe(fd);
     if(ret==-1){
         perror("pipe err");
        exit(1);
     }   
     int i;
     pid_t pid,wpid;
    for(i=0;i<2;i++){					//创建两个子进程
         if((pid=fork())==0)
             break;
     }   
     if(2==i){               				//父进程
         close(fd[0]); 
         close(fd[1]);
         wpid=wait(NULL);
         printf("wait child 1 success,pid=%d\n",wpid);
         pid=wait(NULL);
         printf("wait child 2 success,pid=%d\n",pid);
     }
     else if(i==0){          				//子进程—写
         close(fd[0]);
         dup2(fd[1],STDOUT_FILENO);		//将fd[1]所指文件内容定向到标准输出
         execlp("ls","ls",NULL);
     }
     else if(i==1){          				//子进程—读
         close(fd[1]);
         dup2(fd[0],STDIN_FILENO);
         execlp("wc","wc","-l",NULL);
     }
     return 0;
 }

案例3:使用popen()函数与pclose()函数实现管道通信。

 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 int main()
 {
     FILE *r_fp,*w_fp;
     char buf[100];
     r_fp=popen("ls","r");           	//读取命令执行结果
     w_fp=popen("wc -l","w");        	//将管道中的数据传递给进程
     while(fgets(buf,sizeof(buf),r_fp)!=NULL)
         fputs(buf,w_fp);
     pclose(r_fp);
     pclose(w_fp);
     return 0;
 }

案例4:使用FIFO实现没有亲缘关系进程间的通信。由于是没有亲缘关系的进程间通信,因此需要在两段程序中实现,

这里在程序fifo_write.c中实现FIFO的写操作,在程序fifo_read.c中实现FIFO的读操作。案例实现如下:
fifo_write.c //写

 1#include <stdio.h>
 2#include <stdlib.h>
 3#include <string.h>
 4#include <unistd.h>
 5#include <sys/types.h>
 6#include <sys/stat.h>
 7#include <fcntl.h>
 8int main(int argc,char *argv[])
 9{
 10    if(argc<2)						//判断是否传入文件名
 11    {
 12        printf("./a.out fifoname\n");
 13        exit(1);
 14    }
 15    int ret = access(argv[1],F_OK);	//判断fifo文件是否存在
 16    if(ret==-1)						//若fifo不存在就创建fifo
 17    {   
 18        int r = mkfifo(argv[1],0664);
 19        if(r==-1){					//判断文件是否创建成功
 20            perror("mkfifo");
 21            exit(1);
 22        }
 23        else{
 24            printf("fifo creat success!\n");
 25        }
 26    }
 27    int fd=open(argv[1],O_WRONLY);	//以读写的方式打开文件
 28    while(1){						//循环写入数据
 29        char *p="hello,world!";
 30        write(fd,p,strlen(p)+1);
 31        sleep(1);
 32    }
 33    close(fd);
 34    return 0;
 35}

fifo_read.c //读

 1#include <stdio.h>
 2#include <stdlib.h>
 3#include <string.h>
 4#include <unistd.h>
 5#include <sys/types.h>
 6#include <sys/stat.h>
 7#include <fcntl.h>
 8int main(int argc,char *argv[])
 9{
 10    if(argc<2)							//判断是否传入文件名
 11    {   
 12        printf("./a.out fifoname\n");
 13        exit(1);
 14    }   
 15    int ret = access(argv[1],F_OK);		//判断文件是否存在
 16    if(ret==-1)							//若文件不存在则创建文件
 17    {   
 18        int r = mkfifo(argv[1],0664);
 19        if(r==-1){
 20            perror("mkfifo");
 21            exit(1);
 22        }
 23        else{
 24            printf("fifo creat success!\n");
 25        }
 26    }
 27    int fd = open(argv[1],O_RDONLY);	//打开文件
 28    if(fd==-1){
 29        perror("open");
 30        exit(1);
 31    }
 32    while(1){							//不断读取fifo中的数据并打印
 33        char buf[1024]={0};
 34        read(fd,buf,sizeof(buf));
 35        printf("buf=%s\n",buf);
 36    }
 37    close(fd);							//关闭文件
 38    return 0;
 39}

案例5:使用消息队列实现不同进程间的通信。因为要实现不同进程间的通信,所以此处使用两个程序msgsend.c、msgrcv.c分别作为消息的发送端和接收端。案例实现如下:

msgsend.c //发送端

#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <string.h>
#define MAX_TEXT 512
struct my_msg_st{
long int my_msg_type; 
char anytext[MAX_TEXT]; 
};
int main()
{
    int idx=1;
    int msgid;
    struct my_msg_st data;
    char buf[BUFSIZ];
    msgid=msgget((key_t)1000,0664|IPC_CREAT);
    if(msgid==-1){
        perror("msgget err");
        exit(-1);
    }   
    while(idx<5){
        printf("enter some text:");
        fgets(buf,BUFSIZ,stdin);
        data.my_msg_type=rand()%3+1;
        strcpy(data.anytext,buf);
        
        if(msgsnd(msgid,(void*)&data,sizeof(data),0)==-1){
            perror("msgsnd err");
            exit(-1);
        }
        idx++;
    }
    return 0;
}

msgrcv.c //接收端

#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>
#define MAX_TEXT 512
struct my_msg_st{
    long int my_msg_type;
    char anytext[MAX_TEXT];
};
int main()
{
    int idx=1;
    int msgid;
    struct my_msg_st data;
    long int msg_to_rcv=0;
    msgid=msgget((key_t)1000,0664|IPC_CREAT);
    if(msgid==-1){
        perror("msgget err");
        exit(-1);
    }   
    while(idx<5){
        
        if(msgrcv(msgid,(void*)&data,BUFSIZ,msg_to_rcv,0)==-1){
            perror("msgrcv err");
            exit(-1);
        }
        
        printf("msg type:%ld\n",data.my_msg_type);
        printf("msg content is:%s",data.anytext);
        idx++;
    }
    
    if(msgctl(msgid,IPC_RMID,0)==-1){
        perror("msgctl err");
        exit(-1);
    }
    exit(0);
}

案例6:使用信号量实现父子进程同步,防止父子进程抢夺cpu。案例实现如下:


```javascript
1#include <stdio.h>
 2#include <stdlib.h>
 3#include <sys/sem.h>
 4//自定义共用体
 5union semu{
 6    int val;
 7    struct semid_ds* buf;
 8    unsigned short* array;
 9    struct seminfo* _buf;
 10};
 11static int sem_id;
 12//设置信号量值
 13static int set_semvalue()
 14{
 15    union semu sem_union;
 16    sem_union.val=1;
 17    if(semctl(sem_id,0,SETVAL,sem_union)==-1)
 18        return 0;
 19    return 1;
 20}
 21//p操作,获取信号量
 22static int semaphore_p()
 23{
 24    struct sembuf sem_b;
 25    sem_b.sem_num = 0;
 26    sem_b.sem_op = -1;
 27    sem_b.sem_flg = SEM_UNDO;
 28    if(semop(sem_id,&sem_b,1)==-1){
 29        perror("sem_p err");
 30        return 0;
 31    }
 32    return 1;
 33}
 34//V操作,释放信号量
 35static int semaphore_v()
 36{
 37    struct sembuf sem_b;
 38    sem_b.sem_num=0;
 39    sem_b.sem_op=1;
 40    sem_b.sem_flg=SEM_UNDO;
 41    if(semop(sem_id,&sem_b,1)==-1){
 42        perror("sem_v err");
 43        return 0;
 44    }
 45    return 1;
 46}
 47//删除信号量
 48static void del_semvalue()
 49{
 50    union semu sem_union;
 51    if(semctl(sem_id,0,IPC_RMID,sem_union)==-1)
 52        perror("del err");
 53}
 54int main()
 55{
 56    int i;
 57    pid_t pid;
 58    char ch='C';
 59    sem_id=semget((key_t)1000,1,0664|IPC_CREAT);//创建信号量
 60    if(sem_id==-1){
 61        perror("sem_c err");
 62        exit(-1);
 63    }
 64    if(!set_semvalue()){					//设置信号量值
 65        perror("init err");
 66        exit(-1);
 67    }
 68    pid=fork();								//创建子进程
 69    if(pid==-1){								//若创建失败
 70        del_semvalue();						//删除信号量
 71        exit(-1);
 72    }
 73    else if(pid==0)     						//设置子进程打印的字符
 74        ch='Z';
 75    else										//设置父进程打印的字符
 76        ch='C';
 77    srand((unsigned int)getpid());			//设置随机数种子
 78    for(i=0;i<8;i++)							//循环打印字符
 79    {						
 80        semaphore_p();						//获取信号量
 81        printf("%c",ch);						
 82        fflush(stdout);						//将字符打印到屏幕
 83        sleep(rand()%4);						//沉睡
 84        printf("%c",ch);						
 85        fflush(stdout);						//再次打印到屏幕
 86        sleep(1);
 87        semaphore_v();						//释放信号量
 88    }
 89    if(pid>0){
 90        wait(NULL);							//回收子进程
 91        del_semvalue();						//删除信号量
 92    }
 93    printf("\nprocess %d finished.\n",getpid());			
 94    return 0;
 95}

案例7:创建两个进程,使用共享内存机制实现这两个进程间的通信。 shm_w.c

 1#include <stdio.h>
 2#include <sys/ipc.h>
 3#include <sys/shm.h>
 4#include <sys/types.h>
 5#include <unistd.h>
 6#include <string.h>
 7#define SEGSIZE 4096			//定义共享内存容量
 8typedef struct{					//读写数据结构体
 9	char name[8];
 10	int age;
 11} Stu;
 12int main()
 13{
 14	int shm_id, i;
 15	key_t key;
 16	char name[8];
 17	Stu *smap;
 18	key = ftok("/", 0);			//获取关键字
 19	if (key == -1)
 20	{
 21		perror("ftok error");
 22		return -1;
 23	}
 24	printf("key=%d\n", key);
 25 	//创建共享内存
 26	shm_id = shmget(key, SEGSIZE, IPC_CREAT | IPC_EXCL | 0664);
 27	if (shm_id == -1)
 28	{
 29		perror("create shared memory error\n");
 30		return -1;
 31	}
 32	printf("shm_id=%d\n", shm_id);
 33	smap = (Stu*)shmat(shm_id, NULL, 0);	//将进程与共享内存绑定
 34	memset(name, 0x00, sizeof(name));
 35	strcpy(name, "Jhon");
 36	name[4] = '0';
 37	for (i = 0; i < 3; i++)					//写数据
 38	{
 39		name[4] += 1;
 40		strncpy((smap + i)->name, name, 5);
 41		(smap + i)->age = 20 + i;
 42	}
 1	if (shmdt(smap) == -1)					//解除绑定
 2	{
 3		perror("detach error");
 4		return -1;
 5	}
 43	return 0;
 44}

shm_r.c

6#include <stdio.h>
 7#include <string.h>
 8#include <sys/ipc.h>
 9#include <sys/shm.h>
 10#include <sys/types.h>
 11#include <unistd.h>
 12typedef struct{
 13	char name[8];
 14	int age;
 15} Stu;
 16int main()
 17{
 18	int shm_id, i;
 19	key_t key;
 20	Stu *smap;
 21	struct shmid_ds buf;
 22	key = ftok("/", 0);				//获取关键字
 23	if (key == -1)
 24	{
 25		perror("ftok error");
 26		return -1;
 27	}
 28	printf("key=%d\n", key);
 29	shm_id = shmget(key, 0, 0);		//创建共享内存
 30	if (shm_id == -1)
 31	{
 32		perror("shmget error");
 33		return -1;
 34	}
 35	printf("shm_id=%d\n", shm_id);
 36	smap = (Stu*)shmat(shm_id, NULL, 0);	//将进程与共享内存绑定
 37	for (i = 0; i < 3; i++)					//读数据
 38	{
 39		printf("name:%s\n", (*(smap + i)).name);
 40		printf("age :%d\n", (*(smap + i)).age);
 41	}
 42	if (shmdt(smap) == -1)					//解除绑定
 43	{
 44		perror("detach error");
 45		return -1;
 46	}
 47	shmctl(shm_id, IPC_RMID, &buf);			//删除共享内存
 48	return 0;
 49}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值