【OpenHarmony】IPC之SaMgr的创建

文章目录

ContextObject的设置

openharmony/foundation/systemabilitymgr/samgr/services/samgr/native/source/main.cpp

int main(int argc, char *argv[])
{
    HILOGI("%{public}s called, enter System Ability Manager ", __func__);
    Samgr::MemoryGuard cacheGuard;
    OHOS::sptr<OHOS::SystemAbilityManager> manager = OHOS::SystemAbilityManager::GetInstance();
    manager->Init();
    OHOS::sptr<OHOS::IRemoteObject> serv = manager->AsObject();

    if (!IPCSkeleton::SetContextObject(serv)) {
        HILOGE("set context fail!"); // add log for dfx
    }
    manager->AddSamgrToAbilityMap();
    int result = SetParameter("bootevent.samgr.ready", "true");
    HILOGI("set samgr ready ret : %{public}s", result == 0 ? "succeed" : "failed");
    manager->StartDfxTimer();
    OHOS::IPCSkeleton::JoinWorkThread();
    return -1;
}

openharmony/foundation/communication/ipc/ipc/native/src/core/source/ipc_skeleton.cpp

bool IPCSkeleton::SetContextObject(sptr<IRemoteObject> &object)
{
    IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
    if (current != nullptr) {
        return current->SetRegistryObject(object);
    }
    return false;
}

openharmony/foundation/communication/ipc/ipc/native/src/core/source/ipc_process_skeleton.cpp

bool IPCProcessSkeleton::SetRegistryObject(sptr<IRemoteObject> &object)
{
    CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, false);
    if (object == nullptr) {
        ZLOGE(LOG_LABEL, "object is null");
        return false;
    }
    auto current = ProcessSkeleton::GetInstance();
    if (current == nullptr) {
        ZLOGE(LOG_LABEL, "get process skeleton failed");
        return false;
    }
    IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DEFAULT);
    if (invoker == nullptr) {
        ZLOGE(LOG_LABEL, "fail to get invoker");
        return false;
    }
    bool ret = invoker->SetRegistryObject(object);
    if (ret) {
        current->SetRegistryObject(object);
        current->SetSamgrFlag(true);
    }
    ZLOGI(LOG_LABEL, "set registry result:%{public}d", ret);
    return ret;
}

IRemoteInvoker有两种,BinderInvoder和DBinderDatabusInvoker,BinderInvoker是默认的,看下BinderInvoker的SetRegistryObject
openharmony/foundation/communication/ipc/ipc/native/src/mock/source/binder_invoker.cpp

bool BinderInvoker::SetRegistryObject(sptr<IRemoteObject> &object)
{
    if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
        return false;
    }

    if (object->IsProxyObject()) {
        ZLOGE(LABEL, "set wrong object!");
        return false;
    }

    Parcel dummy;
    int result = binderConnector_->WriteBinder(BINDER_SET_CONTEXT_MGR, &dummy);
    if (result != ERR_NONE) {
        ZLOGE(LABEL, "set registry fail, driver error:%{public}d", result);
        return false;
    }

    return true;
}

openharmony/foundation/communication/ipc/ipc/native/src/mock/source/binder_connector.cpp

int BinderConnector::WriteBinder(unsigned long request, void *value)
{
    int err = -EINTR;

    while (err == -EINTR) {
        if (ioctl(driverFD_, request, value) >= 0) {
            err = ERR_NONE;
        } else {
            err = -errno;
        }

        if (err == -EINTR) {
            ZLOGE(LABEL, "ioctl_binder returned EINTR");
            ReportEvent(DbinderErrorCode::KERNEL_DRIVER_ERROR, std::string(DbinderErrorCode::ERROR_CODE),
                KERNEL_DRIVER_WRITE_IPC_DRIVER_FAILURE, __FUNCTION__);
        }
    }

    return err;
}

WriteBinder就开始和Binder驱动交互,使用系统调用ioctl,给驱动发送BINDER_SET_CONTEXT_MGR命令,参数&dummy:Parcel是哑的,实质在驱动层没有用

openharmony/kernel/linux/linux-5.10/drivers/android/binder.c

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
......
	case BINDER_SET_CONTEXT_MGR_EXT: {
		struct flat_binder_object fbo;

		if (copy_from_user(&fbo, ubuf, sizeof(fbo))) {
			ret = -EINVAL;
			goto err;
		}
		ret = binder_ioctl_set_ctx_mgr(filp, &fbo);
		if (ret)
			goto err;
		break;
	}
	case BINDER_SET_CONTEXT_MGR:
		ret = binder_ioctl_set_ctx_mgr(filp, NULL);
		if (ret)
			goto err;
		break;
.......
}

static int binder_ioctl_set_ctx_mgr(struct file *filp,
				    struct flat_binder_object *fbo)
{
	int ret = 0;
	struct binder_proc *proc = filp->private_data;
	struct binder_context *context = proc->context;
	struct binder_node *new_node;
	kuid_t curr_euid = current_euid();

	mutex_lock(&context->context_mgr_node_lock);
	if (context->binder_context_mgr_node) {
		pr_err("BINDER_SET_CONTEXT_MGR already set\n");
		ret = -EBUSY;
		goto out;
	}
	ret = security_binder_set_context_mgr(proc->cred);
	if (ret < 0)
		goto out;
	if (uid_valid(context->binder_context_mgr_uid)) {
		if (!uid_eq(context->binder_context_mgr_uid, curr_euid)) {
			pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n",
			       from_kuid(&init_user_ns, curr_euid),
			       from_kuid(&init_user_ns,
					 context->binder_context_mgr_uid));
			ret = -EPERM;
			goto out;
		}
	} else {
		context->binder_context_mgr_uid = curr_euid;
	}
	new_node = binder_new_node(proc, fbo);
	if (!new_node) {
		ret = -ENOMEM;
		goto out;
	}
	binder_node_lock(new_node);
	new_node->local_weak_refs++;
	new_node->local_strong_refs++;
	new_node->has_strong_ref = 1;
	new_node->has_weak_ref = 1;
	context->binder_context_mgr_node = new_node;
	binder_node_unlock(new_node);
	binder_put_node(new_node);
out:
	mutex_unlock(&context->context_mgr_node_lock);
	return ret;
}

根据当前进程创建binder_node,并设置为binder_context_mgr_node

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenHarmonyIPC(Inter-Process Communication,进程间通信)主要有以下几种方式: 1. Binder IPC Binder IPC 是一种基于驱动程序的 IPC 方式,是 Android 系统中使用最广泛的 IPC 方式之一。在 OpenHarmony 中,Binder IPC 也被广泛应用于进程间通信,例如应用程序与服务之间的通信、进程间共享数据等。 2. Pipe IPC Pipe IPC 是一种基于文件描述符的 IPC 方式,它可以用于在两个进程之间传递数据。在 OpenHarmony 中,Pipe IPC 可以使用系统调用 pipe、mkfifo、open 等来创建管道,通过读写管道实现进程间通信。 3. Message Queue IPC Message Queue IPC 是一种基于消息的 IPC 方式,它可以用于在两个进程之间传递消息。在 OpenHarmony 中,Message Queue IPC 可以使用系统调用 msgget、msgsnd、msgrcv 等来创建消息队列,通过向消息队列发送和接收消息实现进程间通信。 4. Shared Memory IPC Shared Memory IPC 是一种基于共享内存的 IPC 方式,它可以在多个进程之间共享内存数据。在 OpenHarmony 中,Shared Memory IPC 可以使用系统调用 shmget、shmat、shmdt 等来创建共享内存区域,通过读写共享内存区域实现进程间通信。 5. Socket IPC Socket IPC 是一种基于网络的 IPC 方式,它可以在不同的计算机之间传递数据。在 OpenHarmony 中,Socket IPC 可以使用系统调用 socket、connect、send、recv 等来创建和使用套接字,通过套接字传递数据实现进程间通信。 这些 IPC 方式在 OpenHarmony 中都有广泛的应用,可以根据具体的应用场景选择最合适的 IPC 方式来实现进程间通信。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值