近由于需要弄一些android底层的进程间通讯的东西,所以重温了一下linux的进程通信知识。
进程间通信有很多种方法,使用socket只是其中的一种方法,使用socket的好处呢,就是通用,代码可以在很多平台上直接编译,效率也很高的。
实际上,在android系统中,绝大多数的API 都使用了socket与底层的本地服务通信,这样做到了应用程序接口和底层框架分离的原则。用这种方式封装的API 更加安全,不存在代码进入内核态的问题,也不存在函数堆栈溢出的问题。所以说android系统比传统的操作系统更加安全是有道理的。
下面是一个通用的linux的socket IPC的例子,这个例子的详细解释可以参照这里的描述:http://blog.csdn.net/xnwyd/article/details/7359506
这个例子的好处呢,就是通用,在所有的linux系统下均可以编译使用。经测试,在x86和arm下都可以正常使用。
这个例子我编译的时候使用了arm c语言的交叉编译环境,至于如何搭建arm交叉编译环境,可以参照这里的方法:http://tweetyf.org/2013/04/using_the_android_toolchain_as_a_standalone_compiler.html
另外,如果你有android的源代码编译环境,且需要把自己编译的本地服务集成到系统中的话,有更加简洁的方法创建和编译系统服务,这个下回再做介绍。
server.c 编译方法:arm-linux-androideabi-gcc -o server server.c
01#include<sys/types.h>
02#include<sys/socket.h>
03#include<stdio.h>
04#include<sys/un.h>
05#include<unistd.h>
06#include<stdlib.h>
07#include <stddef.h>
08
09#define SERVER_NAME "@server_socket"
10/*
11 * Create a UNIX-domain socket address in the Linux "abstract namespace".
12 *
13 * The socket code doesn't require null termination on the filename, but
14 * we do it anyway so string functions work.
15 */
16int makeAddr(const char* name, struct sockaddr_un* pAddr, socklen_t* pSockLen)
17{
18 int nameLen = strlen(name);
19 if (nameLen >= (int) sizeof(pAddr->sun_path) -1) /* too long? */
20 return -1;
21 pAddr->sun_path[0] = '\0'; /* abstract namespace */
22 strcpy(pAddr->sun_path+1, name);
23 pAddr->sun_family = AF_UNIX;
24 *pSockLen = 1 + nameLen + offsetof(struct sockaddr_un, sun_path);
25 return 0;
26}
27
28int main()
29
30{
31 int server_sockfd, client_sockfd;
32 socklen_t server_len, client_len;
33 struct sockaddr_un server_addr;
34 struct sockaddr_un client_addr;
35 char ch;
36 int nread;
37
38 //delete the old server socket
39 //unlink("server_socket");
40 //create socket
41 server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
42
43 //name the socket
44 server_addr.sun_family = AF_UNIX;
45 strcpy(server_addr.sun_path, SERVER_NAME);
46 server_addr.sun_path[0]=0;
47 //server_len = sizeof(server_addr);
48 server_len = strlen(SERVER_NAME) + offsetof(struct sockaddr_un, sun_path);
49 //makeAddr("server_socket", &server_addr, &server_len);
50 bind(server_sockfd, (struct sockaddr *)&server_addr, server_len);
51
52 //listen the server
53 listen(server_sockfd, 5);
54 client_sockfd = -1;
55 client_len = sizeof(client_addr);
56 while(1){
57 printf("server waiting...\n");
58 //accept client connect
59 if(client_sockfd == -1){
60 client_sockfd = accept(server_sockfd,(struct sockaddr*)&client_addr, &client_len);
61 }
62
63 //read data from client socket
64 nread = read(client_sockfd, &ch, 1);
65 if(nread == 0){//client disconnected
66 printf("client %d disconnected\n",client_sockfd);
67 client_sockfd = -1;
68 }
69 else{
70 printf("read from client %d: %c\n",client_sockfd,ch);
71 ch ++;
72 write(client_sockfd, &ch, 1);
73 }
74 usleep(100);//1000 miliseconds = 1 second
75 }
76
77 return 0;
78
79}
client.c 编译:arm-linux-androideabi-gcc -o client client.c
01#include<sys/types.h>
02#include<sys/socket.h>
03#include<stdio.h>
04#include<sys/un.h>
05#include<unistd.h>
06#include<stdlib.h>
07#include <stddef.h>
08#define SERVER_NAME "@server_socket"
09/*
10 * Create a UNIX-domain socket address in the Linux "abstract namespace".
11 *
12 * The socket code doesn't require null termination on the filename, but
13 * we do it anyway so string functions work.
14 */
15int makeAddr(const char* name, struct sockaddr_un* pAddr, socklen_t* pSockLen)
16{
17 int nameLen = strlen(name);
18 if (nameLen >= (int) sizeof(pAddr->sun_path) -1) /* too long? */
19 return -1;
20 pAddr->sun_path[0] = '\0'; /* abstract namespace */
21 strcpy(pAddr->sun_path+1, name);
22 pAddr->sun_family = AF_UNIX;
23 *pSockLen = 1 + nameLen + offsetof(struct sockaddr_un, sun_path);
24 return 0;
25}
26
27int main()
28{
29 int sockfd;
30 socklen_t len;
31 struct sockaddr_un address;
32 int result;
33 char ch = 'A';
34
35 //create socket
36 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
37 //name the server socket
38 //makeAddr("server_socket", &address, &len);
39 address.sun_family = AF_UNIX;
40 strcpy(address.sun_path, SERVER_NAME);
41 address.sun_path[0]=0;
42 //len = sizeof(address);
43 len = strlen(SERVER_NAME) + offsetof(struct sockaddr_un, sun_path);
44 //connect to server
45 result = connect(sockfd, (struct sockaddr*)&address, len);
46 if(result == -1)
47 {
48 perror("opps:client1");
49 exit(1);
50 }
51 //communicate with server socket
52 while(1)
53 {
54 printf("set send content:");
55 scanf("%c",&ch);
56 write(sockfd, &ch, 1);
57 printf("send to server:%c \n",ch);
58 read(sockfd, &ch, 1);
59 printf("read from server: %c\n", ch);
60
61 }
62 exit(0);
63
64}
分别把client 和 server 上传到arm的板子或者 android手机上,用命令行执行就可以测试效果了。
本文地址:http://tweetyf.org/2013/06/use_socket_ipc_arm.html