Trusty, iki uygulama/hizmet sınıfı geliştirmek için API'ler sağlar:
- TEE işlemcide çalışan güvenilir uygulamalar veya hizmetler
- Ana işlemcide çalışan ve sağlanan hizmetleri kullanan normal/güvenilmeyen uygulamalar güvenilir uygulamalara göre
Trusty API genellikle Trusty işlemler arası iletişim (IPC) sistemini güvenli olmayan dünyayla iletişim de dahil olmak üzere. ana işlemci, güvenilir uygulamalara/hizmetlere bağlanmak için Trusty API'lerini kullanabilir ve IP üzerinden bir ağ hizmeti gibi rastgele mesajlar gönderip alabilirsiniz. Bu verilerin biçimini ve anlamını belirlemek uygulamaya bağlıdır uygulama düzeyinde bir protokol kullanarak İletilerin güvenilir bir şekilde teslim edilmesi temel Trusty altyapısı tarafından garanti edilir (sürücüler biçiminde ana işlemci üzerinde çalışıyor) ve iletişim tamamen eşzamansız.
Bağlantı noktaları ve kanallar
Bağlantı noktaları, Trusty uygulamaları tarafından hizmet uç noktalarını biçimde sunmak için kullanılır
bir ad verilmiş olması gerekir. Bu yöntem basit, dize tabanlı
kullanacağı hizmet kimliğidir. Adlandırma kuralı ters DNS stilidir
adlandırma, ör. com.google.servicename
İstemci bir bağlantı noktasına bağlandığında, istemci etkileşim için bir kanal alır sahip olacaksınız. Hizmetin gelen bir bağlantıyı kabul etmesi gerekir ve aynı şekilde kanal alır. Temelde, bağlantı noktaları hizmet aramak için kullanılır. Daha sonra iletişim, iki bağlı kanal (ör. bağlantı örnekleri) için geçerlidir. İstemci bir bağlantı noktasına bağlandığında simetrik iki yönlü bağlantı kurulduğunda. İstemciler bu tam çift yönlü yolu kullanarak Sunucular, her iki taraf da ortadan kaldırmaya karar verene kadar rastgele mesajlar gönderip alabilir. bağlantıyı keser.
Yalnızca güvenli taraftaki güvenilir uygulamalar veya Trusty çekirdek modülleri bağlantı noktaları. Güvenli olmayan tarafta çalışan uygulamalar (normal dünyada) yalnızca güvenli tarafından yayınlanan hizmetlere bağlanmalıdır.
Gereksinimlere bağlı olarak, güvenilir bir uygulama hem istemci hem de ekleyebileceğiniz anlamına gelir. Hizmeti yayınlayan ( sunucusu) diğer hizmetlere (istemci olarak) bağlanması gerekebilir.
Herkese açık kullanıcı adı API'si
Herkese açık kullanıcı adları, bağlantı noktaları ve bağlantı noktaları gibi kaynakları temsil eden imzasız tam sayılardır. UNIX'teki dosya tanımlayıcılarına benzer. Herkese açık kullanıcı adları oluşturulduktan sonra uygulamaya özel bir herkese açık kullanıcı adı tablosuna yerleştirilir ve daha sonra.
Arayan, herkese açık kullanıcı adı için şunları kullanarak gizli verileri bir herkese açık kullanıcı adıyla ilişkilendirebilir:
set_cookie()
yöntemi.
Handle API'deki Yöntemler
Herkese açık kullanıcı adları yalnızca bir uygulama bağlamında geçerlidir. Başvuru,
herkese açık kullanıcı adı açıkça belirtilmediği sürece
belirtiliyor. Herkese açık kullanıcı adı değeri, yalnızca
bir uygulamanın kullanabileceği INVALID_IPC_HANDLE #define,
bir herkese açık kullanıcı adının geçersiz olduğunu veya ayarlanmadığını gösterir.
set_cookie()
Arayan tarafından sağlanan gizli verileri, belirtilen bir herkese açık kullanıcı adıyla ilişkilendirir.
long set_cookie(uint32_t handle, void *cookie)
[içinde] handle
: API çağrılarından biri tarafından döndürülen herkese açık kullanıcı adı
[in] cookie
: Trusty uygulamasındaki rastgele kullanıcı alanı verilerine işaretçi
[retval]: başarılı sonuçta NO_ERROR
, aksi takdirde < 0
hata kodu
Bu çağrı, daha sonra gerçekleşen etkinliklerin işlenmesinde yararlıdır. herkese açık kullanıcı adı oluşturuldu. Etkinlik işleme mekanizması, herkese açık kullanıcı adını sağlar. ve çerezini etkinlik işleyiciye geri gönderir.
Herkese açık kullanıcı adları, wait()
çağrısı kullanılarak etkinliklerde beklenebilir.
Wait()
Bir etkinliğin belirli bir süre boyunca, belirli bir herkese açık kullanıcı adında gerçekleşmesini bekler.
long wait(uint32_t handle_id, uevent_t *event, unsigned long timeout_msecs)
[içinde] handle_id
: API çağrılarından biri tarafından döndürülen herkese açık kullanıcı adı
[out] event
: Yapıyı temsil eden bir işaretçi
bu herkese açık kullanıcı adında gerçekleşen bir etkinlik
[in] timeout_msecs
: Milisaniye cinsinden zaman aşımı değeri; CANNOT TRANSLATE
-1 değeri sonsuz bir zaman aşımıdır
[retval]: NO_ERROR
belirtilen zaman aşımı aralığı; Belirtilen bir zaman aşımı süresi geçmişse ancak hiç zaman aşımı olmuşsa ERR_TIMED_OUT
Etkinlik gerçekleştiyse; Diğer hatalar için < 0
Başarı üzerine (retval == NO_ERROR
), wait()
araması
belirtilen bir uevent_t
yapısını
önemli bir nokta.
typedef struct uevent { uint32_t handle; /* handle this event is related to */ uint32_t event; /* combination of IPC_HANDLE_POLL_XXX flags */ void *cookie; /* cookie associated with this handle */ } uevent_t;
event
alanı aşağıdaki değerlerin bir kombinasyonunu içerir:
enum { IPC_HANDLE_POLL_NONE = 0x0, IPC_HANDLE_POLL_READY = 0x1, IPC_HANDLE_POLL_ERROR = 0x2, IPC_HANDLE_POLL_HUP = 0x4, IPC_HANDLE_POLL_MSG = 0x8, IPC_HANDLE_POLL_SEND_UNBLOCKED = 0x10, … more values[TBD] };
IPC_HANDLE_POLL_NONE
: Gerçekte beklemede olan hiçbir etkinlik yok.
arayan, beklemeyi yeniden başlatmalıdır
IPC_HANDLE_POLL_ERROR
- Belirlenemeyen bir dahili hata oluştu
IPC_HANDLE_POLL_READY
- aşağıdaki gibi herkese açık kullanıcı adı türüne bağlıdır:
- Bağlantı noktaları için bu değer, beklemede olan bir bağlantı olduğunu gösterir
- Kanallar için bu değer, eşzamansız bir bağlantının
(bkz.
connect()
) kuruldu
Aşağıdaki etkinlikler yalnızca kanallar için geçerlidir:
IPC_HANDLE_POLL_HUP
, kanalın bir eş tarafından kapatıldığını gösterirIPC_HANDLE_POLL_MSG
: Bu kanal için bekleyen bir mesaj olduğunu gösterirIPC_HANDLE_POLL_SEND_UNBLOCKED
- daha önce gönderen engellenen arayan, mesajı tekrar gönderin (ayrıntılar içinsend_msg()
açıklamasına bakın)
Bir etkinlik işleyici, belirtilen kombinasyonun bir kombinasyonunu işleyecek şekilde hazırlanmalıdır. etkinlikleri için de önemlidir. Örneğin, olabilir, bu nedenle beklemedeki mesajlar olabilir ve bağlantınız aynı anda sizinle iletişim kurabiliyor.
Çoğu etkinlik sabittir. Temel koşul devam ettiği sürece
devam eder (örneğin, bekleyen tüm iletiler alınmıştır ve bağlantı beklemededir
emin olun. Ancak bir istisna olan
IPC_HANDLE_POLL_SEND_UNBLOCKED
etkinliği
durumu okunduğunda temizlenir ve uygulamanın yalnızca bir kez
ele alacağız.
Herkese açık kullanıcı adları, close()
yöntemi çağrılanarak kaldırılabilir.
kapat()
Belirtilen herkese açık kullanıcı adıyla ilişkilendirilmiş kaynağı kaldırır ve hedefi şuradan kaldırır: kullanıcı adı tablosu.
long close(uint32_t handle_id);
[in] handle_id
: Yok etmek için tutma yeri
[retval]: başarılıysa 0; aksi takdirde negatif bir hata oluşur
Sunucu API'si
Sunucu, başlangıç ayarlarını temsil eden bir veya daha fazla adlandırılmış bağlantı noktası uç noktalara gider. Her bağlantı noktası bir herkese açık kullanıcı adıyla temsil edilir.
Server API'deki yöntemler
port_create()
Adlandırılmış bir hizmet bağlantı noktası oluşturur.
long port_create (const char *path, uint num_recv_bufs, size_t recv_buf_size, uint32_t flags)
[içinde] path
: Bağlantı noktasının dize adı (yukarıda açıklandığı gibi). Bu
ad, sistem genelinde benzersiz olmalıdır; başarısız olur.
[in] num_recv_bufs
: Bir kanalın bulunduğu maksimum tampon sayısı
bu bağlantı noktası, istemciyle veri alışverişini kolaylaştırmak için önceden tahsis edilebilir. Tamponlar sayılır
her iki yönde giden veriler için ayrı ayrı olduğundan burada 1'in belirtilmesi 1 anlamına gelir
gönder ve 1 alma arabelleği önceden tahsis edildi. Genel olarak tampon sayısı
gereklilik, istemci ile istemci arasındaki üst düzey protokol sözleşmesine bağlıdır.
sunucu. Çok eşzamanlı bir protokol söz konusu olduğunda sayı 1 kadar küçük olabilir.
(ileti gönder, başka bir ileti göndermeden önce yanıt al). Ancak bu sayı
bir yanıt gönderemeden birden fazla mesaj göndermeyi beklerse
(ör.bir mesaj giriş olarak, başka bir mesaj da gerçek komut olarak gösterilir). İlgili içeriği oluşturmak için kullanılan
ayrılan arabellek kümelerinin her kanal için geçerli olduğundan, iki ayrı bağlantı (kanallar)
ayrı tampon kümeleri olur.
[in] recv_buf_size
:
üst sınır grubudur. Bu değer
protokole bağlıdır ve gönderip alabileceğiniz maksimum ileti boyutunu etkili bir şekilde sınırlar
eş ile
[içinde] flags
: Ek bağlantı noktası davranışı belirten işaretlerin kombinasyonu
Bu değer, aşağıdaki değerlerin bir kombinasyonu olmalıdır:
IPC_PORT_ALLOW_TA_CONNECT
- Diğer güvenli uygulamalardan bağlantıya izin verir
IPC_PORT_ALLOW_NS_CONNECT
- güvenli olmayan dünyadan bağlantıya izin verir
[retval]: Negatif değilse oluşturulan bağlantı noktasını veya negatif
Sunucu daha sonra gelen bağlantılar için bağlantı noktası tanıtıcılarının listesini yoklar.
wait()
arama kullanılıyor. Bağlantı aldıktan sonra
isteği,IPC_HANDLE_POLL_READY
uevent_t
yapısının event
alanı,
sunucu bağlantı kurmayı bitirmek ve biraccept()
kanal (
herkese açık kullanıcı adı) gelen iletiler için sorgulanabilir.
kabul()
Gelen bağlantıyı kabul eder ve kanalın herkese açık kullanıcı adını belirler.
long accept(uint32_t handle_id, uuid_t *peer_uuid);
[içinde] handle_id
: İstemcinin bağlandığı bağlantı noktasını temsil eden tutma yeri
[out] peer_uuid
: Toplanacak uuid_t
yapısının işaretçisi
bağlanan istemci uygulamasının UUID'siyle doldurulur. Google
bağlantı güvenli olmayan dünyadan geliyorsa hepsi sıfır olarak ayarlanır
[retval]: Sunucunun oluşturabileceği bir kanalı (negatif değilse) istemciyle mesaj alışverişi (veya başka bir hata kodu ile)
İstemci API'si
Bu bölümde, Client API'deki yöntemler yer almaktadır.
Client API'deki Yöntemler
Connect()
Adı belirtilen bir bağlantı noktasına bağlantı başlatır.
long connect(const char *path, uint flags);
[içinde] path
: Bir Trusty uygulaması tarafından yayınlanan bağlantı noktasının adı
[içinde] flags
: Ek, isteğe bağlı davranışı belirtir
[retval]: Mesajları sunucu; negatifse hata
flags
belirtilmezse (flags
parametresi)
0 olarak ayarlanırsa connect()
çağrısı yapıldığında eşzamanlı bir bağlantı başlatılır
hemen aynı bağlantı noktasına
bağlantı noktası yoksa bir hata döndürür ve
sunucu aksi takdirde bağlantı kabul eder.
Bu davranış, iki değerin bir kombinasyonunu belirterek değiştirilebilir: aşağıda açıklanmıştır:
enum { IPC_CONNECT_WAIT_FOR_PORT = 0x1, IPC_CONNECT_ASYNC = 0x2, };
IPC_CONNECT_WAIT_FOR_PORT
- connect()
öğesini zorlar
belirtilen bağlantı noktası yürütme sırasında hemen mevcut değilse bekleme çağrısı,
yardımcı olur.
IPC_CONNECT_ASYNC
: Ayarlanırsa eşzamansız bağlantı başlatır.
uygulamanın
herkese açık kullanıcı adı için wait()
IPC_HANDLE_POLL_READY
tarafından belirtilen bir bağlantı tamamlama etkinliği
başlamadan önce uevent_t
yapısının etkinlik alanında ayarlanmış bit
normal çalışma.
Mesajlaşma API'si
Messaging API çağrıları, önceden oluşturulmuş bağlantı (kanal). Messaging API çağrıları, aynı şekilde kullanır.
Bir müşteri, connect()
vererek kanalın herkese açık kullanıcı adını alır
çağrısı ile sunucu tarafından accept()
çağrısından kanalın herkese açık kullanıcı adı alınırsa
'ne başvurun.
Trusty mesajının yapısı
Aşağıda gösterildiği gibi, Trusty API'nin gönderdiği mesajlar minimum düzeydedir. yapılandırmanın anlamları üzerinde anlaşmak için sunucuya ve müşteriye gerçek içerik:
/* * IPC message */ typedef struct iovec { void *base; size_t len; } iovec_t; typedef struct ipc_msg { uint num_iov; /* number of iovs in this message */ iovec_t *iov; /* pointer to iov array */ uint num_handles; /* reserved, currently not supported */ handle_t *handles; /* reserved, currently not supported */ } ipc_msg_t;
Bir mesaj, zaman çizelgesiyle temsil edilen bir veya daha fazla bitişik olmayan tampondan
iovec_t
yapısı dizisidir. Trusty, dağılım toplama işlemi yapıyor
bu blokları okur ve yazar
iov
dizisi kullanılır. Açıklanabilecek tamponların içeriği
iov
dizisi tamamen rastgeledir.
Messaging API'deki yöntemler
send_msg()
Belirli bir kanal üzerinden mesaj gönderir.
long send_msg(uint32_t handle, ipc_msg_t *msg);
[içinde] handle
: Mesajın gönderileceği kanalı yönlendirme
[in] msg
: Mesajı açıklayan ipc_msg_t structure
öğesinin işaretçisi
[retval]: Başarıyla gönderilen toplam bayt sayısı; aksi takdirde negatif bir hata oluşur
İstemci (veya sunucu) kanal üzerinden bir mesaj göndermeye çalışıyorsa ve
hedef benzerler mesajları sırasında boşluk yoksa kanal
bir gönderme engellendi durumu girin (basit bir eşzamanlı iletimlerde bu hiçbir zaman
daha karmaşık durumlarda yaşanabilir).
ERR_NOT_ENOUGH_BUFFER
hata kodu döndürülmesiyle gösterilir.
Bu tür bir durumda arayan, akran biraz serbest bırakıncaya kadar beklemelidir
alma sırasında bir alana geri dönmek için
IPC_HANDLE_POLL_SEND_UNBLOCKED
uevent_t
yapısının event
alanı
wait()
araması tarafından döndürüldü.
get_msg()
Gelen ileti sırasındaki bir sonraki iletiyle ilgili meta bilgileri alır
bir feed'dir.
long get_msg(uint32_t handle, ipc_msg_info_t *msg_info);
[şurada] handle
: Yeni mesajın alınması gereken kanalın herkese açık kullanıcı adı
[out] msg_info
: İleti bilgilerinin yapısı aşağıda açıklanmıştır:
typedef struct ipc_msg_info { size_t len; /* total message length */ uint32_t id; /* message id */ } ipc_msg_info_t;
Her bir iletiye, bekleyen iletiler kümesindeki benzersiz bir kimlik atanır. ve her mesajın toplam uzunluğu girilir. protokolü kullanıyorsanız, aynı anda birden çok bekleyen (açık) ileti olabilir. söz konusu olabilir.
[retval]: NO_ERROR
başarılı; aksi takdirde negatif bir hata oluşur
Read_msg()
İletinin içeriğini belirtilen uzaklık.
long read_msg(uint32_t handle, uint32_t msg_id, uint32_t offset, ipc_msg_t *msg);
[şurada] handle
: Mesajın okunacağı kanalın herkese açık kullanıcı adı
[in] msg_id
: Okunacak iletinin kimliği
[içinde] offset
: Okumaya başlamak için mesajda ofset
[out] msg
: Şu özellikleri açıklayan ipc_msg_t
yapısının işaretçisi:
gelen iletinin saklanacağı bir tampon grubu
veri
[retval]: Şu tarihlerde msg
arabelleklerinde depolanan toplam bayt sayısı
başarı, aksi takdirde negatif bir hata oluşur
read_msg
yöntemi, şu değerden itibaren birden fazla kez çağrılabilir:
farklı (her zaman
sıralı) ofseti kullanabilirsiniz.
put_msg()
Belirtilen kimliğe sahip bir iletiyi kullanımdan kaldırır.
long put_msg(uint32_t handle, uint32_t msg_id);
[şurada] handle
: Mesajın ulaştığı kanalın herkese açık kullanıcı adı
[içinde] msg_id
: Kullanımdan kaldırılan iletinin kimliği
[retval]: NO_ERROR
başarılı; aksi takdirde negatif bir hata oluşur
Bir ileti kullanımdan kaldırıldıktan sonra ileti içeriğine erişilememesi boşa çıkarılmıştır.
File Descriptor API'sı
File Descriptor API şunları içerir: read()
, write()
,
ve ioctl()
arama. Bu çağrıların tümü önceden tanımlanmış (statik) bir dosya grubu üzerinde çalışabilir
geleneksel olarak küçük sayılarla temsil edilen tanımlayıcılar. Şu anda
uygulaması için, dosya açıklayıcı alanı, IPC herkese açık kullanıcı adından ayrıdır.
boşluk oluşturur. Trusty'deki File Descriptor API,
geleneksel dosya tanımlayıcı tabanlı API'ye benzer.
Varsayılan olarak, önceden tanımlanmış 3 dosya tanımlayıcısı (standart ve iyi bilinen) vardır:
- 0 - standart giriş. Standart girişin varsayılan uygulaması:
fd
no-operatördür (güvenilir uygulamaların etkileşimli konsolu) olduğundan,fd
0 üzerindeioctl()
okuma, yazma veya çağrılmaERR_NOT_SUPPORTED
hatası döndürecektir. - 1 - standart çıkış. Standart çıkışa yazılan veriler yönlendirilebilir (bağlı olarak
LK hata ayıklama düzeyinde) UART'a ve/veya güvenli olmayan SDK'da bulunan bir bellek günlüğüne
değişiklik gösterir. Kritik olmayan hata ayıklama günlükleri ve
mesajların standart çıkışta gönderilmesi gerekir.
read()
veioctl()
yöntemleri işlemsizdir veERR_NOT_SUPPORTED
hatası verir. - 2 - standart hata. Standart hataya yazılan veriler UART'a yönlendirilmelidir
Bu işlem platforma ve platforma bağlı olarak güvenli olmayan tarafta
kullanılabilen bellek günlüğü veya
yapılandırma. Standart iletilere yalnızca kritik iletileri yazmanız önerilir
büyük olasılıkla kısıtlanmamıştır.
read()
veioctl()
yöntemleri işlemsiz değil veERR_NOT_SUPPORTED
hatası döndürecek.
Söz konusu dosya tanımlayıcıları kümesi, daha fazla kullanıcı
fds
(platforma özel uzantılar uygulamak için), dosya tanımlayıcıları ihtiyaçlarının kapsamını genişletiyor
dikkatli olunmalıdır. Dosya tanımlayıcılarının genişletilmesi genellikle
olduğundan genellikle önerilmez.
File Descriptor API'deki Yöntemler
Read()
Belirtilen dosya tanımlayıcısından count
bayta kadar veriyi okumaya çalışır.
long read(uint32_t fd, void *buf, uint32_t count);
[in] fd
: Okunacak dosya tanımlayıcısı
[out] buf
: Verilerin depolanacağı tamponu işaret eder
[şunun içinde] count
: Okunacak maksimum bayt sayısı
[retval]: Okunan bayt sayısı döndürülür; aksi takdirde negatif bir hata oluşur
Write()
Belirtilen dosya tanımlayıcısına count
bayta kadar veri yazar.
long write(uint32_t fd, void *buf, uint32_t count);
[in] fd
: Yazılacak dosya tanımlayıcısı
[out] buf
: Yazılacak verilerin işaretçisi
[şunun içinde] count
: Yazılacak maksimum bayt sayısı
[retval]: Yazılan bayt sayısı; aksi takdirde negatif bir hata oluşur
ioctl()
Belirli bir dosya açıklayıcı için belirli bir ioctl
komutunu çağırır.
long ioctl(uint32_t fd, uint32_t cmd, void *args);
[içinde] fd
: ioctl()
çağrılacak dosya tanımlayıcısı
[içinde] cmd
: ioctl
komutu
[in/out] args
: ioctl()
bağımsız değişkene işaret eden
Çeşitli API
Çeşitli API'deki Yöntemler
gettime()
Geçerli sistem zamanını döndürür (nanosaniye cinsinden).
long gettime(uint32_t clock_id, uint32_t flags, int64_t *time);
[in] clock_id
: Platforma bağımlı; varsayılan için sıfırı geç
[içinde] flags
: Ayrılmış, sıfır olmalıdır
[out] time
: Geçerli zamanın depolanacağı bir int64_t
değerine işaret eder
[retval]: NO_ERROR
başarılı; aksi takdirde negatif bir hata oluşur
nanosleep()
Çağrı uygulamasının yürütülmesini belirli bir süre için askıya alır bu sürenin ardından da devam ettirilir.
long nanosleep(uint32_t clock_id, uint32_t flags, uint64_t sleep_time)
[içinde] clock_id
: Ayrılmış, sıfır olmalıdır
[içinde] flags
: Ayrılmış, sıfır olmalıdır
[in] sleep_time
: Nanosaniye cinsinden uyku süresi
[retval]: NO_ERROR
başarılı; aksi takdirde negatif bir hata oluşur
Güvenilir uygulama sunucusu örneği
Aşağıdaki örnek uygulama, yukarıdaki API'lerin kullanımını göstermektedir. Örnek "yankı" oluşturuyor birden fazla gelen bağlantıyı işleyen ve Kaynaktan gelen istemcilerden aldığı tüm mesajları arayana yansıtır. güvenli olmayan taraftan çıkarır.
#include <uapi/err.h> #include <stdbool.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <trusty_ipc.h> #define LOG_TAG "echo_srv" #define TLOGE(fmt, ...) \ fprintf(stderr, "%s: %d: " fmt, LOG_TAG, __LINE__, ##__VA_ARGS__) # define MAX_ECHO_MSG_SIZE 64 static const char * srv_name = "com.android.echo.srv.echo"; static uint8_t msg_buf[MAX_ECHO_MSG_SIZE]; /* * Message handler */ static int handle_msg(handle_t chan) { int rc; struct iovec iov; ipc_msg_t msg; ipc_msg_info_t msg_inf; iov.iov_base = msg_buf; iov.iov_len = sizeof(msg_buf); msg.num_iov = 1; msg.iov = &iov; msg.num_handles = 0; msg.handles = NULL; /* get message info */ rc = get_msg(chan, &msg_inf); if (rc == ERR_NO_MSG) return NO_ERROR; /* no new messages */ if (rc != NO_ERROR) { TLOGE("failed (%d) to get_msg for chan (%d)\n", rc, chan); return rc; } /* read msg content */ rc = read_msg(chan, msg_inf.id, 0, &msg); if (rc < 0) { TLOGE("failed (%d) to read_msg for chan (%d)\n", rc, chan); return rc; } /* update number of bytes received */ iov.iov_len = (size_t) rc; /* send message back to the caller */ rc = send_msg(chan, &msg); if (rc < 0) { TLOGE("failed (%d) to send_msg for chan (%d)\n", rc, chan); return rc; } /* retire message */ rc = put_msg(chan, msg_inf.id); if (rc != NO_ERROR) { TLOGE("failed (%d) to put_msg for chan (%d)\n", rc, chan); return rc; } return NO_ERROR; } /* * Channel event handler */ static void handle_channel_event(const uevent_t * ev) { int rc; if (ev->event & IPC_HANDLE_POLL_MSG) { rc = handle_msg(ev->handle); if (rc != NO_ERROR) { /* report an error and close channel */ TLOGE("failed (%d) to handle event on channel %d\n", rc, ev->handle); close(ev->handle); } return; } if (ev->event & IPC_HANDLE_POLL_HUP) { /* closed by peer. */ close(ev->handle); return; } } /* * Port event handler */ static void handle_port_event(const uevent_t * ev) { uuid_t peer_uuid; if ((ev->event & IPC_HANDLE_POLL_ERROR) || (ev->event & IPC_HANDLE_POLL_HUP) || (ev->event & IPC_HANDLE_POLL_MSG) || (ev->event & IPC_HANDLE_POLL_SEND_UNBLOCKED)) { /* should never happen with port handles */ TLOGE("error event (0x%x) for port (%d)\n", ev->event, ev->handle); abort(); } if (ev->event & IPC_HANDLE_POLL_READY) { /* incoming connection: accept it */ int rc = accept(ev->handle, &peer_uuid); if (rc < 0) { TLOGE("failed (%d) to accept on port %d\n", rc, ev->handle); return; } handle_t chan = rc; while (true){ struct uevent cev; rc = wait(chan, &cev, INFINITE_TIME); if (rc < 0) { TLOGE("wait returned (%d)\n", rc); abort(); } handle_channel_event(&cev); if (cev.event & IPC_HANDLE_POLL_HUP) { return; } } } } /* * Main application entry point */ int main(void) { int rc; handle_t port; /* Initialize service */ rc = port_create(srv_name, 1, MAX_ECHO_MSG_SIZE, IPC_PORT_ALLOW_NS_CONNECT | IPC_PORT_ALLOW_TA_CONNECT); if (rc < 0) { TLOGE("Failed (%d) to create port %s\n", rc, srv_name); abort(); } port = (handle_t) rc; /* enter main event loop */ while (true) { uevent_t ev; ev.handle = INVALID_IPC_HANDLE; ev.event = 0; ev.cookie = NULL; /* wait forever */ rc = wait(port, &ev, INFINITE_TIME); if (rc == NO_ERROR) { /* got an event */ handle_port_event(&ev); } else { TLOGE("wait returned (%d)\n", rc); abort(); } } return 0; }
run_end_to_end_msg_test()
yöntemi,eşzamansız olarak 10.000 mesaj gönderir
"yankı"ya hizmet ve herkese açık kullanıcı adları
yanıt.
static int run_echo_test(void) { int rc; handle_t chan; uevent_t uevt; uint8_t tx_buf[64]; uint8_t rx_buf[64]; ipc_msg_info_t inf; ipc_msg_t tx_msg; iovec_t tx_iov; ipc_msg_t rx_msg; iovec_t rx_iov; /* prepare tx message buffer */ tx_iov.base = tx_buf; tx_iov.len = sizeof(tx_buf); tx_msg.num_iov = 1; tx_msg.iov = &tx_iov; tx_msg.num_handles = 0; tx_msg.handles = NULL; memset (tx_buf, 0x55, sizeof(tx_buf)); /* prepare rx message buffer */ rx_iov.base = rx_buf; rx_iov.len = sizeof(rx_buf); rx_msg.num_iov = 1; rx_msg.iov = &rx_iov; rx_msg.num_handles = 0; rx_msg.handles = NULL; /* open connection to echo service */ rc = sync_connect(srv_name, 1000); if(rc < 0) return rc; /* got channel */ chan = (handle_t)rc; /* send/receive 10000 messages asynchronously. */ uint tx_cnt = 10000; uint rx_cnt = 10000; while (tx_cnt || rx_cnt) { /* send messages until all buffers are full */ while (tx_cnt) { rc = send_msg(chan, &tx_msg); if (rc == ERR_NOT_ENOUGH_BUFFER) break; /* no more space */ if (rc != 64) { if (rc > 0) { /* incomplete send */ rc = ERR_NOT_VALID; } goto abort_test; } tx_cnt--; } /* wait for reply msg or room */ rc = wait(chan, &uevt, 1000); if (rc != NO_ERROR) goto abort_test; /* drain all messages */ while (rx_cnt) { /* get a reply */ rc = get_msg(chan, &inf); if (rc == ERR_NO_MSG) break; /* no more messages */ if (rc != NO_ERROR) goto abort_test; /* read reply data */ rc = read_msg(chan, inf.id, 0, &rx_msg); if (rc != 64) { /* unexpected reply length */ rc = ERR_NOT_VALID; goto abort_test; } /* discard reply */ rc = put_msg(chan, inf.id); if (rc != NO_ERROR) goto abort_test; rx_cnt--; } } abort_test: close(chan); return rc; }
Güvenli olmayan API'ler ve uygulamalar
Güvenli tarafta yayınlanan ve
IPC_PORT_ALLOW_NS_CONNECT
özelliğine, çekirdek tarafından erişilebilir.
ve kullanıcı alanında çalışan
güvenli olmayan tarafını belirler.
Güvenli olmayan taraftaki yürütme ortamı (çekirdek ve kullanıcı alanı) bu, güvenli taraftaki yürütme ortamından önemli ölçüde farklıdır. Dolayısıyla, her iki ortam için tek bir kitaplık yerine, her iki ortam için de farklı API'ler oluşturabilirsiniz. Çekirdekteki Client API, güvenilir-ipc çekirdek sürücüsü ve kullanılabilecek bir karakter cihaz düğümünü kaydeder güvenli bağlantıda çalışan hizmetlerle iletişim kurmak için kullanıcı yanı sıra.
Kullanıcı alanı Trusty IPC Client API
Kullanıcı alanı Trusty IPC Client API kitaplığı,
fd
cihaz düğümü.
Kullanıcı alanı programı bir iletişim oturumu başlatır
tipc_connect()
numaralı telefonu arayarak
belirtilen bir Trusty hizmetiyle bağlantı başlatılıyor. Dahili olarak,
tipc_connect()
çağrısı, belirtilen cihaz düğümünü açar ve
bir dosya tanımlayıcısı alır ve bir TIPC_IOC_CONNECT ioctl()
çağırır
bir dizeyi işaret eden argp
parametresiyle
hizmet adını seçin.
#define TIPC_IOC_MAGIC 'r' #define TIPC_IOC_CONNECT _IOW(TIPC_IOC_MAGIC, 0x80, char *)
Ortaya çıkan dosya tanımlayıcısı, yalnızca hizmetle iletişim kurmak için kullanılabilir.
örnek olarak verilebilir. Dosya tanımlayıcısı,
bağlantı artık gerekli olmadığında tipc_close()
aranıyor.
tipc_connect()
çağrısıyla elde edilen dosya tanımlayıcısı
tipik bir karakter cihaz düğümü gibi davranır; dosya tanımlayıcısı:
- Gerekirse engellemeyen moda geçilebilir
- Standart bir
write()
kullanılarak yazılabilir karşı tarafa mesaj göndermek için ara - Anket yapılabilir (
poll()
veyaselect()
arama kullanılarak) gelen iletilerin normal bir dosya tanımlayıcısı olarak kullanılabilirliği için - Gelen mesajları almak için okunabilir
Arayan,
belirtilen fd
. Tüm veriler yukarıdaki write()
çağrısına iletildi
güvenilir-ipc sürücüsü tarafından bir mesaja dönüştürülür. Mesaj
güvenli tarafa teslim edilir. Buradaki veriler, IPC alt sistemi tarafından
Trusty çekirdeğinin çekirdeği doğru hedefe yönlendirilmiş ve bir uygulamaya iletilmiştir.
belirli bir kanalda IPC_HANDLE_POLL_MSG
etkinliği olarak etkinlik döngüsü
herkese açık kullanıcı adı. İlgili özelliğe bağlı olarak,
protokolü kullanıyorsanız, Trusty hizmeti bir veya daha fazla yanıt
güvenli olmayan tarafa geri teslim edilen ve güvenli olmayan tarafa
kullanıcı tarafından alınacak uygun kanal dosyası açıklayıcı mesaj sırası
alan uygulaması read()
çağrısı.
tipc_connect()
Belirtilen tipc
cihaz düğümünü açar ve bir başlatma işlemi
belirtilen bir Trusty hizmetine bağlanma.
int tipc_connect(const char *dev_name, const char *srv_name);
[içinde] dev_name
: Açılacak Trusty IPC cihaz düğümünün yolu
[içinde] srv_name
: Bağlanılacak yayınlanmış bir Trusty hizmetinin adı
[retval]: Başarıyla ilgili geçerli dosya tanımlayıcısı, aksi takdirde -1 değeri.
tipc_close()
Bir dosya tanımlayıcısı tarafından belirtilen Trusty hizmetiyle olan bağlantıyı kapatır.
int tipc_close(int fd);
[şurada] fd
: Dosya tanımlayıcısı daha önce şu kullanıcı tarafından açılmış:
tipc_connect()
araması
Kernel Trusty IPC İstemci API'si
Çekirdek Trusty IPC Client API, çekirdek sürücüleri için kullanılabilir. Kullanıcı bu API'ye ek olarak Space Trusty IPC API uygulanmış.
Genel olarak, bu API'nin tipik kullanımında,
tipc_create_channel()
kullanarak bir struct tipc_chan
nesnesi
işlevini başlatmak için tipc_chan_connect()
çağrısını kullanarak
güvenli bağlantıda çalışan Trusty IPC hizmetine
yanı sıra. Uzak tarafla olan bağlantı Google tarafından
tipc_chan_shutdown()
aranıyor, ardından şu numara kullanılıyor:
Kaynakları temizlemek için tipc_chan_destroy()
.
Bildirim alındığında (handle_event()
geri araması üzerinden)
bağlantısı kurulduğunda, arayan,
şu:
tipc_chan_get_txbuf_timeout()
çağrısını kullanarak bir ileti arabelleği alır- Bir ileti oluşturur ve
tipc_chan_queue_msg()
kullanarak iletiyi sıraya alır güvenli tarafta) teslim etmek için kullanılan yöntem, kanal bağlı
Sıraya alma işlemi başarılı olduktan sonra, arayanın mesaj arabelleğini unutması gerekir
çünkü ileti arabelleği,
tarafından işleme konur (daha sonra diğer iletiler için yeniden kullanmak üzere). Kullanıcı
, yalnızca şu başarısız olduğunda tipc_chan_put_txbuf()
öğesini çağırması gerekir:
sıraya sokabilir veya artık gerekmeyebilir.
Bir API kullanıcısı, bir
handle_msg()
bildirim geri çağırması (
güvenilir-ipc rx
iş sırasının bağlamını ele alalım.
içeren bir rx
arabelleğine işaretçi sağlar:
emin olmanız gerekir.
handle_msg()
geri çağırması beklenir
uygulanması bir işaretçiyi geçerli bir struct tipc_msg_buf
öğesine döndürür.
Yerel olarak işleniyorsa gelen ileti arabelleğiyle aynı olabilir
ve artık gerekli değil. Alternatif olarak,
gelen arabellek sıraya alındıysa tipc_chan_get_rxbuf()
çağrısı
göz atın. Ayrı bir rx
tamponu takip edilmelidir
ve nihayetinde bir tipc_chan_put_rxbuf()
çağrısıyla yayınlandı.
artık ihtiyacınız yok.
Kernel Trusty IPC Client API'deki Yöntemler
tipc_create_channel()
Belirli bir kullanıcı için Trusty IPC kanalının bir örneğini oluşturur ve yapılandırır güvenilir-ipc cihazı.
struct tipc_chan *tipc_create_channel(struct device *dev, const struct tipc_chan_ops *ops, void *cb_arg);
[in] dev
: Cihazın bulunduğu güvenilir IP'nin işaretçisi
kanal oluşturuldu
[in] ops
: struct tipc_chan_ops
işaretçisi,
arayana özel
geri arama dolduruldu
[in] cb_arg
: Aktarılacak verilerin işaretçisi
tipc_chan_ops
geri arama
[retval]: Yeni oluşturulmuş bir örneğine işaret eden
struct tipc_chan
başarı,
Aksi durumda ERR_PTR(err)
Genel olarak, bir çağrıyı yapan, eşzamansız olarak çağrılan iki geri çağırma sağlamalıdır. en iyi uygulamaları gözden geçirmelisiniz.
void (*handle_event)(void *cb_arg, int event)
etkinliği çağrılır
bir arayanı kanal durumu değişikliği konusunda bilgilendirmek için kullanılır.
[in] cb_arg
:
tipc_create_channel()
araması
[in] event
: Aşağıdaki değerlerden biri olabilecek bir etkinlik:
TIPC_CHANNEL_CONNECTED
- bağlantının başarılı olduğunu gösterir uzak tarafaTIPC_CHANNEL_DISCONNECTED
: Uzak tarafın reddettiğini gösterir veya yeni bağlantı isteğinde bulunulduğunda daha önce bağlanmış olan kanalın bağlantısı kesilirTIPC_CHANNEL_SHUTDOWN
: Uzak tarafın kapandığını belirtir. tüm bağlantıları kalıcı olarak sonlandırma
struct tipc_msg_buf *(*handle_msg)(void *cb_arg, struct tipc_msg_buf *mb)
Yeni bir mesaj olduğuna dair bildirim sağlamak için geri arama çağrılır
Belirli bir kanal üzerinden alınan:
- [in]
cb_arg
:tipc_create_channel()
araması - [in]
mb
:struct tipc_msg_buf
işaretçisi gelen bir mesajı açıklıyor - [retval]: Geri çağırma uygulamasının bir işaretçiyi
Alınan aynı işaretçi olabilecek
struct tipc_msg_buf
olarak Mesaj yerel olarak işleniyorsa ve işlenmiyorsamb
parametresi (veyatipc_chan_get_rxbuf()
çağrısıyla edinilen yeni bir tampon olabilir)
tipc_chan_connect()
Belirtilen Trusty IPC hizmetiyle bağlantı başlatır.
int tipc_chan_connect(struct tipc_chan *chan, const char *port);
[in] chan
: Kullanıcının döndürdüğü kanala
tipc_create_chan()
araması
[in] port
: İmleci
bağlanılacak hizmet adı
[retval]: Başarıda 0, aksi takdirde olumsuz bir hata vardır
Bir bağlantı kurulduğunda, arayan kişiye bir
handle_event
geri arama.
tipc_chan_shutdown()
Daha önce başlatılan Trusty IPC hizmetiyle olan bağlantıyı sonlandırır
tipc_chan_connect()
aramasıyla.
int tipc_chan_shutdown(struct tipc_chan *chan);
[içinde] chan
: Şu kullanıcı tarafından döndürülen kanalın işaretçisi:
tipc_create_chan()
araması
tipc_chan_INSTALL()
Belirtilen bir Trusty IPC kanalını kaldırır.
void tipc_chan_destroy(struct tipc_chan *chan);
[in] chan
: Kullanıcının döndürdüğü kanala
tipc_create_chan()
araması
tipc_chan_get_txbuf_timeout()
Belirli bir üzerinden veri göndermek için kullanılabilecek bir mesaj arabelleği alır yardımcı olur. Arabellek hemen kullanılamıyorsa arayan kişi engellenebilir belirtilen zaman aşımı süresi için (milisaniye cinsinden).
struct tipc_msg_buf * tipc_chan_get_txbuf_timeout(struct tipc_chan *chan, long timeout);
[içinde] chan
: İmleci, iletinin sıraya alınacağı kanala yönlendirir
[in] chan
: Şu saate kadar beklemek için maksimum zaman aşımı
tx
arabelleği kullanılabilir hale gelir
[retval]: Başarıda geçerli bir mesaj tamponu
Hata durumunda ERR_PTR(err)
tipc_chan_kuyruğu_msg()
Bir iletiyi, belirtilen iletinin üzerinden gönderilecek şekilde sıraya alır Güvenilir IPC kanalları.
int tipc_chan_queue_msg(struct tipc_chan *chan, struct tipc_msg_buf *mb);
[içinde] chan
: İletinin sıraya alınacağı kanalın işaretçisi
[in] mb:
İşaretçiyi sıraya alacak iletinin üzerine getirin
(tipc_chan_get_txbuf_timeout()
çağrısı ile elde edilir)
[retval]: Başarıda 0, aksi takdirde olumsuz bir hata vardır
tipc_chan_put_txbuf()
Belirtilen Tx
mesaj arabelleğini serbest bırakır
daha önce bir tipc_chan_get_txbuf_timeout()
aramasıyla edinilmiş bilgilerdir.
void tipc_chan_put_txbuf(struct tipc_chan *chan, struct tipc_msg_buf *mb);
[in] chan
: İşaretçi olan kanal
bu mesaj arabelleği yine
[içinde] mb
: Serbest bırakmak için mesaj arabelleğinin işaretçisi
[retval]: Yok
tipc_chan_get_rxbuf()
belirtilen kanal.
struct tipc_msg_buf *tipc_chan_get_rxbuf(struct tipc_chan *chan);
[şurada] chan
: Bu mesaj arabelleğinin ait olduğu kanalın işaretçisi
[retval]: Başarılı olduğunda geçerli bir mesaj arabelleği, hata durumunda ERR_PTR(err)
tipc_chan_put_rxbuf()
Bir
tipc_chan_get_rxbuf()
arama.
void tipc_chan_put_rxbuf(struct tipc_chan *chan, struct tipc_msg_buf *mb);
[şurada] chan
: Bu mesaj arabelleğinin ait olduğu kanalın işaretçisi
[içinde] mb
: Serbest bırakmak için ileti arabelleğinin işaretçisi
[retval]: Yok