您的位置:首页 > 其它

和菜鸟一起深入学习国嵌实验之进程间通信

2013-02-03 11:47 531 查看
1、 无名管道

代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>

int main(int argc, char *argv[])
{
pid_t pid;
int pipe_fd[2];
char buf_r[100];
char *p_wbuf;
int r_num;

memset(buf_r, 0, sizeof(buf_r));

if(pipe(pipe_fd) < 0)
{
printf("pipe create error\n");
return -1;
}

//create child process
if((pid = fork()) == 0)
{
printf("\n");
close(pipe_fd[1]);
sleep(2);

if((r_num = read(pipe_fd[0], buf_r, 100)) > 0)
printf("%d numbers read from the pipe is %s\n", r_num, buf_r);

close(pipe_fd[0]);

exit(0);

}
else if(pid > 0)
{
close(pipe_fd[0]);
if(write(pipe_fd[1], "Hello", 5) != -1)
printf("parent write1 Hello\n");
if(write(pipe_fd[1], "Pipe", 5) != -1)
printf("parent write2 Pipe\n");

close(pipe_fd[1]);
waitpid(pid, NULL, 0);
exit(0);
}

return 0;
}


Makefile:

CC = gcc

CURTDIR = $(shell pwd)
TARGET = mypipe

%.o:%.c
$(CC)-c $(EXTRAFLAGS) $< -o $@
%.o:%.S
$(CC)-c $(EXTRAFLAGS) $< -o $@

.PHONY: all clean

$(TARGET): $(TARGET).o
$(CC)  -o $@ $^

clean:
rm-rf $(TARGET) $(TARGET).o


运行结果:

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.1$make
gcc -c mypipe.c -o mypipe.o
gcc -o mypipe mypipe.o

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.1$ls
Makefile mypipe  mypipe.c  mypipe.o

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.1$./mypipe
parent write1 Hello
parent write2 Pipe

10 numbers read from the pipe is HelloPipe

结论:由于fork函数让子进程完整地拷贝了父进程的整个地址空间,所以父子进程都有管道的读端和写端。而我们需要的是一个进程读,一个进程写,所以写的进程最好关闭读端,读的进程关闭写端。

2、 有名管道

代码1:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#define FIFO_SERVER "/tmp/myfifo"

int main(int argc, char *argv[])
{
int fd;
char w_buf[100];
int nwrite;

if((mkfifo(FIFO_SERVER, O_CREAT | O_EXCL | O_RDWR) < 0)
&& (errno!= EEXIST))
printf("cannot create fifoserver\n");

fd = open(FIFO_SERVER, O_RDWR | O_NONBLOCK, 0);
if(fd == -1)
{
perror("open");
exit(1);
}

if(argc == 1)
{
printf("please send something\n");
exit(-1);
}

strcpy(w_buf, argv[1]);
if((nwrite == write(fd, w_buf, 100)) == -1)
{
if(errno == EAGAIN)
printf("The FIFO has not been read yet. please try later\n");
}
else
printf("write %s to the FIFO\n", w_buf);

close(fd);

return 0;
}


代码2:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#define FIFO_SERVER "/tmp/myfifo"

int main(int argc, char *argv[])
{
int fd;
char buf_r[100];
int nread;

if((mkfifo(FIFO_SERVER, O_CREAT | O_EXCL | O_RDWR) < 0)
&& (errno!= EEXIST))
printf("cannot create fifoserver\n");

fd = open(FIFO_SERVER, O_RDWR | O_NONBLOCK, 0);
if(fd == -1)
{
perror("open");
exit(1);
}

while(1)
{
memset(buf_r, 0, sizeof(buf_r));
if(nread = read(fd, buf_r, 100) == -1)
{
if(errno == EAGAIN)
printf("no datayet\n");
}
printf("read %s from FIFO\n", buf_r);
sleep(1);
}

close(fd);
pause();
unlink(FIFO_SERVER);

return 0;
}


Makefile:

CC = gcc

CURTDIR = $(shell pwd)
TARGET = myfifo_write
#TARGET = myfifo_read

%.o:%.c
$(CC)-c $(EXTRAFLAGS) $< -o $@
%.o:%.S
$(CC)-c $(EXTRAFLAGS) $< -o $@

.PHONY: all clean

$(TARGET): $(TARGET).o
$(CC)  -o $@ $^

clean:
rm-rf $(TARGET) $(TARGET).o
rm-rf $(TARGETR) $(TARGETR).o


运行结果:

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.2$sudo ./myfifo_write hello
write hello to the FIFO
eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.2$sudo ./myfifo_write fifo
write fifo to the FIFO

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.2$sudo ./myfifo_read
no data yet
read from FIFO
no data yet
read from FIFO
no data yet
read from FIFO
read hello from FIFO
no data yet
read from FIFO
read fifo from FIFO
no data yet
read from FIFO

总结:先创建一个有名管道,打开管道之后向管道中写入由主函数传入的字符串,然后另一个进程循环从管道中读取数据。当没有数据时,是读不到的,当有数据时,就可以读到了。

3、 信号处理

代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <signal.h>

void my_func(int sign_no)
{
if(sign_no == SIGBUS)
{
printf("I have get SIGBUS\n");
}
}

int main(int argc, char *argv[])
{
printf("Waiting for signal SIGBUS\n");

signal(SIGBUS, my_func);

pause();
return 0;
}


Makefile:

CC = gcc

CURTDIR = $(shell pwd)
TARGET = mysig

%.o:%.c
$(CC)-c $(EXTRAFLAGS) $< -o $@
%.o:%.S
$(CC)-c $(EXTRAFLAGS) $< -o $@

.PHONY: all clean

$(TARGET): $(TARGET).o
$(CC)  -o $@ $^

clean:
rm-rf $(TARGET) $(TARGET).o


运行结果:

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$make
gcc -c mysig.c -o mysig.o
gcc -o mysig mysig.o

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$ls
Makefile mysig  mysig.c  mysig.o

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$./mysig
Waiting for signal SIGBUS
eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$ps -aux | grep mysig
Warning: bad ps syntax, perhaps a bogus'-'? See http://procps.sf.net/faq.html eastmoon 10270  0.0 0.4   9116  3124 pts/2   S+   15:09   0:00 vi mysig.txt
eastmoon 10295  0.0 0.0   1728   244 pts/3   S+   15:10   0:00 ./mysig
eastmoon 10300  0.0 0.1   5804   876 pts/4   S+   15:11   0:00 grep --color=auto mysig
eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$kill -BUS 10295

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.3$./mysig
Waiting for signal SIGBUS
I have get SIGBUS


总结:signal系统调用为SIGBUS信号注册了信号处理函数,然后将进程挂起等待SIGBUS信号,当向该进程发送SIGBUS信号才会执行信号处理函数。

4、 共享内存

代码1:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <signal.h>
#include "shm_com.h"

int main(int argc, char *argv[])
{
int running = 1;
void *shared_memory = (void*)0;
struct shared_use_st *shared_stuff;
int shmid;

shmid = shmget((key_t)1234, sizeof(struct shared_use_st),
0666|IPC_CREAT);

if(shmid == -1)
{
fprintf(stderr, "shmget failed\n");
exit(EXIT_FAILURE);
}

shared_memory = shmat(shmid, (void*)0, 0);
if(shared_memory == (void*)-1)
{
fprintf(stderr, "shmmat failed\n");
exit(EXIT_FAILURE);
}
printf("Memory attached at %x\n", (int)shared_memory);

shared_stuff = (struct shared_use_st *)shared_memory;

shared_stuff->written_by_you = 0;

while(running)
{
if(shared_stuff->written_by_you)
{
printf("You wrote: %s\n", shared_stuff->some_text);
sleep(1);
shared_stuff->written_by_you = 0;
if(strncmp(shared_stuff->some_text, "end", 3) == 0)
{
running = 0;
}
}
}

if(shmdt(shared_memory) == -1)
{
fprintf(stderr, "shmmdt failed\n");
exit(EXIT_FAILURE);
}

return 0;
}


代码2:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <signal.h>
#include "shm_com.h"

int main(int argc, char *argv[])
{
int running = 1;
void *shared_memory = (void*)0;
struct shared_use_st *shared_stuff;
char buffer[BUFSIZ];
int shmid;

shmid = shmget((key_t)1234, sizeof(struct shared_use_st),
0666|IPC_CREAT);

if(shmid == -1)
{
fprintf(stderr, "shmget failed\n");
exit(EXIT_FAILURE);
}

shared_memory = shmat(shmid, (void*)0, 0);
if(shared_memory == (void*)-1)
{
fprintf(stderr, "shmmat failed\n");
exit(EXIT_FAILURE);
}
printf("Memory attached at %x\n", (int)shared_memory);

shared_stuff = (struct shared_use_st *)shared_memory;

shared_stuff->written_by_you = 0;

while(running)
{
while(shared_stuff->written_by_you)
{
sleep(1);
printf("Waiting for client....\n");
}

printf("Enter some text: ");
fgets(buffer, BUFSIZ, stdin);
strncpy(shared_stuff->some_text, buffer, TEXT_SZ);
shared_stuff->written_by_you = 1;
if(strncmp(buffer, "end", 3) == 0)
{
running = 0;
}
}

if(shmdt(shared_memory) == -1)
{
fprintf(stderr, "shmmdt failed\n");
exit(EXIT_FAILURE);
}

return 0;
}


代码3:

#define TEXT_SZ 2048

struct shared_use_st
{
int written_by_you;
char some_text[TEXT_SZ];
};


Makefile:

CC = gcc

CURTDIR = $(shell pwd)
#TARGET = myshm1
TARGET = myshm2

%.o:%.c
$(CC)-c $(EXTRAFLAGS) $< -o $@
%.o:%.S
$(CC)-c $(EXTRAFLAGS) $< -o $@

.PHONY: all clean

$(TARGET): $(TARGET).o
$(CC)  -o $@ $^

clean:
rm-rf $(TARGET) $(TARGET).o


运行结果:

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$make
gcc -c myshm1.c -o myshm1.o
gcc -o myshm1 myshm1.o
eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$ls
Makefile myshm1  myshm1.c  myshm1.o myshm2.c  shm_com.h

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$make
gcc -c myshm2.c -o myshm2.o
gcc -o myshm2 myshm2.o
eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$ls
Makefile myshm1  myshm1.c  myshm1.o myshm2  myshm2.c  myshm2.o shm_com.h

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$./myshm1
Memory attached at b78db000

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$./myshm2
Memory attached at b7731000
Enter some text: my first share memory
Waiting for client....
Waiting for client....
Enter some text: it's so good
Waiting for client....
Waiting for client....
Enter some text: ok, now let's study otherthings.
Waiting for client....
Waiting for client....
Enter some text: end

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.4$./myshm1
Memory attached at b78db000
You wrote: my first share memory

You wrote: it's so good

You wrote: ok, now let's study otherthings.

You wrote: end


总结:用于通信的两个进程必须用同一块共享内存进行通信,所以shmget的第一个参数key必须是相同的。

5、 消息队列

代码1:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>

struct my_msg_st
{
long int my_msg_type;
char some_text[BUFSIZ];
};

int main(int argc, char *argv[])
{
int running = 1;
int msgid;
struct my_msg_st some_data;
long int msg_to_receive = 0;

msgid = msgget((key_t)2222, 0666 | IPC_CREAT);
if(msgid == -1)
{
fprintf(stderr, "msgget failed with error: %d\n", errno);
exit(EXIT_FAILURE);
}

while(running)
{
if(msgrcv(msgid, (void*)&some_data, BUFSIZ, msg_to_receive, 0) ==-1)
{
fprintf(stderr, "msgrcv failed with error: %d\n", errno);
exit(EXIT_FAILURE);
}

printf("You wrote: %s\n", some_data.some_text);

if(strncmp(some_data.some_text, "end", 3) == 0)
{
running = 0;
}
}

if(msgctl(msgid, IPC_RMID, 0) == -1)
{
fprintf(stderr, "msgctl failed with error: %d\n", errno);
exit(EXIT_FAILURE);
}

return 0;
}


代码2:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>

struct my_msg_st
{
long int my_msg_type;
char some_text[BUFSIZ];
};

int main(int argc, char *argv[])
{
int running = 1;
int msgid;
struct my_msg_st some_data;
char buffer[BUFSIZ];

msgid= msgget((key_t)2222, 0666 | IPC_CREAT);
if(msgid == -1)
{
fprintf(stderr, "msgget failed with error: %d\n", errno);
exit(EXIT_FAILURE);
}

while(running)
{
printf("Enter some text:");
fgets(buffer, BUFSIZ, stdin);

some_data.my_msg_type = 1;
strcpy(some_data.some_text, buffer);

if(msgsnd(msgid, (void*)&some_data, BUFSIZ, 0) == -1)
{
fprintf(stderr, "msgsnd failed with error: %d\n", errno);
exit(EXIT_FAILURE);
}

if(strncmp(some_data.some_text, "end", 3) == 0)
{
running = 0;
}
}

return 0;
}


Makefile:

CC = gcc

CURTDIR = $(shell pwd)
TARGET = mymsg1
#TARGET = mymsg2

%.o:%.c
$(CC)-c $(EXTRAFLAGS) $< -o $@
%.o:%.S
$(CC)-c $(EXTRAFLAGS) $< -o $@

.PHONY: all clean

$(TARGET): $(TARGET).o
$(CC)  -o $@ $^

clean:
rm-rf $(TARGET) $(TARGET).o


运行结果:

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$make
gcc -c mymsg1.c -o mymsg1.o
gcc -o mymsg1 mymsg1.o

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$ls
Makefile mymsg1  mymsg1.c  mymsg1.o

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$make
gcc -c mymsg2.c -o mymsg2.o
gcc -o mymsg2 mymsg2.o

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$ls
Makefile mymsg1  mymsg1.c  mymsg1.o mymsg2  mymsg2.c  mymsg2.o

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$./mymsg2
Enter some text:hello
Enter some text:mymsg
Enter some text:good-buy
Enter some text:end

eastmoon@eastmoon-virtual-machine:~/work/guoqian/2/2.5$./mymsg1
You wrote: hello

You wrote: mymsg

You wrote: good-buy

You wrote: end


总结:在没有运行msg2向消息队列中添加消息的时候,msg1会阻塞在msgrcv函数上,运行msg2后,每添加一条消息,msg1就读取一条,直到添加的消息为”end”,结束。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: