这道题想考察什么?
Linux IPC方式
int main(void) {
int n, fd[2];
char buf[SIZE];
//生成一对描述符,一个用来写,一个用来读。
pipe(fd);//生成一对管道描述符,fd[1]用于写,fd[0]用于读
pid_t pid = fork();//fork调用创建了子进程,子进程会继承这一对管道描述符
//想父进程往子进程中写东西
if (pid == 0) {//子进程
close(fd[1]);//将子进程的写的描述符关了
read(fd[0], buf, SIZE);//子进程就从读的描述符中将字符串读出来
} else if (pid > 0) {//父进程
close(fd[0]); //将父进程的读的描述符关了
write(fd[1], "Hello", 5);//父进程往写的描述中写入一个字符串
}
}
示意图如下:
父进程的读描述符fd[0]关闭,子进程的写描述符fd[1]关闭;
父进程的写描述符fd[1]写入数据,子进程的读描述符fd[0]读取数据。
FrameWork中的管道使用
//Android 6.0之前使用管道,之后使用eventfd
Looper::Looper(bool allowNonCallbacks) {
int wakeFds[2];
int result = pipe(wakeFds);
mWakeReadPipeFd = wakeFds[0];//读
mWakeWritePipeFd = wakeFds[1];//写
...
mEpollFd = epoll_create(EPOLL_SIZE_HINT);//创建epoll
struct epoll_event eventItem;
eventItem.events = EPOLLIN;
eventItem.data.fd = mWakeReadPipeFd;
//监听读事件
epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
}
int Looper::pollInner(int timeoutMillis) {
struct epoll_event eventItems[EPOLL_MAX_EVENTS];
//epoll_wait阻塞等待事件,eventCount表示有几个事件被触发了
int eventCount = epoll_wait(mEpollFd, eventItems, …);
for (int i = 0; i < eventCount; i++) {
int fd = eventItems[i].data.fd;
uint32_t epollEvents = eventItems[i].events;
if (fd == mWakeReadPipeFd) { //是读描述符
if (epollEvents & EPOLLIN) {
awoken();//读数据
}
}
}
......
return result;
}
//写
void Looper::wake() {
nWrite = write(mWakeWritePipeFd, "W", 1);
}
管道和epoll结合,监听读写事件
管道:在数据量不怎么大的跨进程通信的时候使用
//mian是Zygote的入口函数
public static void main(String argv[]) {
......
//创建了ZygoteSocket
registerZygoteSocket(socketName);
......
runSelectLoop(abiList);
}
void runSelectLoop(String abiList) {
……
while (true) {
Os.poll(pollFds, -1);
for (int i = pollFds.length - 1; i >= 0; --i) {
if (i == 0) {
// 处理新过来的连接
} else {
// 处理发过来的数据
peers.get(i).runOnce();
}
}
}
}
进程间大数据量传输的,主要图像相关的
//工具类,封装了Android的Ashmem共享机制-匿名共享内存
public MemoryFile(String name, int length) {
mLength = length;
mFD = native_open(name, length);
mAddress = native_mmap(mFD, length, PROT_READ | PROT_WRITE);
}
native_open :ashmem_create_region(namestr, length);创建匿名共享内存
native_mmap:mmap(NULL, length, prot, MAP_SHARED, fd, 0);映射到当前进程的内存空间,内存空间的地址就是mAddress。
jint android_os_MemoryFile_read(JNIEnv* env, jobject clazz, …) {
……
env->SetByteArrayRegion(buffer, destOffset, count, …);
……
return count;
}
jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz, ...) {
……
env->GetByteArrayRegion(buffer, srcOffset, count, …);
……
return count;
}
public class Process {
//杀掉应用进程
public static final void killProcess(int pid) {
sendSignal(pid, SIGNAL_KILL);//发送SIGNAL_KILL信号
}
}
static void SetSigChldHandler() {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SigChldHandler;
//Zygote关注的信号
//Zygote启动子进程后,要关注子进程是否退出
sigaction(SIGCHLD, &sa, NULL);
}