Trusty มี API สำหรับการพัฒนาแอปและบริการ 2 ระดับ ได้แก่
- แอปและบริการที่เชื่อถือได้ซึ่งทำงานบนโปรเซสเซอร์ TEE
- แอปทั่วไปและแอปที่ไม่น่าเชื่อถือที่ทำงานบนโปรเซสเซอร์หลักและใช้บริการที่แอปที่เชื่อถือได้จัดหาให้
โดยทั่วไปแล้ว Trusty API จะอธิบายระบบการสื่อสารระหว่างกระบวนการ (IPC) ของ Trusty รวมถึงการสื่อสารกับโลกที่ไม่ปลอดภัย ซอฟต์แวร์ที่ทำงานบนตัวประมวลผลหลักสามารถใช้ Trusty API เพื่อเชื่อมต่อกับแอปและบริการที่เชื่อถือได้ และแลกเปลี่ยนข้อความกับแอปและบริการเหล่านั้นได้เช่นเดียวกับบริการเครือข่ายผ่าน IP โดยแอปจะเป็นผู้กำหนดรูปแบบข้อมูลและความหมายของข้อความเหล่านี้โดยใช้โปรโตคอลระดับแอป การส่งข้อความที่เชื่อถือได้ได้รับการรับประกันโดยโครงสร้างพื้นฐาน Trusty ที่อยู่เบื้องหลัง (ในรูปแบบของไดรเวอร์ที่ทำงานบนโปรเซสเซอร์หลัก) และการสื่อสารเป็นแบบไม่พร้อมกันโดยสมบูรณ์
พอร์ตและช่อง
แอปที่เชื่อถือได้จะใช้พอร์ตเพื่อแสดงปลายทางบริการในรูปแบบเส้นทางที่มีชื่อซึ่งไคลเอ็นต์เชื่อมต่อ ซึ่งจะให้รหัสบริการแบบสตริงที่เรียบง่ายสำหรับไคลเอ็นต์ รูปแบบการตั้งชื่อเป็นแบบ DNS แบบย้อนกลับ เช่น com.google.servicename
เมื่อไคลเอ็นต์เชื่อมต่อกับพอร์ต ไคลเอ็นต์จะได้รับช่องทางสำหรับการโต้ตอบกับบริการ บริการต้องยอมรับการเชื่อมต่อขาเข้า และเมื่อยอมรับแล้ว บริการก็จะได้รับช่องด้วย โดยพื้นฐานแล้ว พอร์ตจะใช้เพื่อค้นหาบริการ จากนั้นการสื่อสารจะเกิดขึ้นผ่านคู่แชแนลที่เชื่อมต่อกัน (เช่น อินสแตนซ์การเชื่อมต่อบนพอร์ต) เมื่อไคลเอ็นต์เชื่อมต่อกับพอร์ต ระบบจะสร้างการเชื่อมต่อแบบ 2 ทิศทางแบบสมมาตร เมื่อใช้เส้นทางแบบ Full-Duplex นี้ ไคลเอ็นต์และเซิร์ฟเวอร์จะแลกเปลี่ยนข้อความแบบใดก็ได้จนกว่าฝ่ายใดฝ่ายหนึ่งจะตัดสินใจปิดการเชื่อมต่อ
เฉพาะแอปที่เชื่อถือได้ฝั่งที่ปลอดภัยหรือโมดูลเคอร์เนล Trusty เท่านั้นที่สร้างพอร์ตได้ แอปที่ทำงานในด้านที่ไม่ปลอดภัย (ในโลกปกติ) จะเชื่อมต่อได้เฉพาะกับบริการที่เผยแพร่โดยฝั่งที่ปลอดภัย
แอปที่เชื่อถือได้อาจเป็นทั้งไคลเอ็นต์และเซิร์ฟเวอร์ในเวลาเดียวกัน ทั้งนี้ขึ้นอยู่กับข้อกำหนด แอปที่เชื่อถือได้ซึ่งเผยแพร่บริการ (ในฐานะเซิร์ฟเวอร์) อาจต้องเชื่อมต่อกับบริการอื่นๆ (ในฐานะไคลเอ็นต์)
Handle API
แฮนเดิลคือจำนวนเต็มแบบไม่ลงนามที่แสดงถึงทรัพยากร เช่น พอร์ตและแชแนล ซึ่งคล้ายกับตัวระบุไฟล์ใน UNIX หลังจากสร้างแฮนเดิลแล้ว ระบบจะใส่แฮนเดิลเหล่านั้นลงในตารางแฮนเดิลเฉพาะแอปและสามารถอ้างอิงภายหลังได้
ผู้เรียกสามารถเชื่อมโยงข้อมูลส่วนตัวกับแฮนเดิลได้โดยใช้เมธอด set_cookie()
เมธอดใน Handle API
แฮนเดิลจะใช้ได้เฉพาะในบริบทของแอปเท่านั้น แอปไม่ควรส่งค่าของแฮนเดิลไปยังแอปอื่นๆ เว้นแต่จะระบุไว้อย่างชัดเจน ค่าของแฮนเดิลควรตีความโดยการเปรียบเทียบกับ INVALID_IPC_HANDLE #define,
เท่านั้น ซึ่งแอปสามารถใช้เป็นข้อบ่งชี้ว่าแฮนเดิลไม่ถูกต้องหรือไม่ได้รับการตั้งค่า
set_cookie()
เชื่อมโยงข้อมูลส่วนตัวที่ผู้โทรระบุไว้กับแฮนเดิลที่ระบุ
long set_cookie(uint32_t handle, void *cookie)
[in] handle
: แฮนเดิลที่การเรียก API ใดเรียกให้แสดง
[in] cookie
: ตัวชี้ไปยังข้อมูลพื้นที่ผู้ใช้แบบไม่เจาะจงในแอป Trusty
[retval]: NO_ERROR
เมื่อดำเนินการสำเร็จ หรือ < 0
เมื่อดำเนินการไม่สำเร็จ
การเรียกใช้นี้จะมีประโยชน์ในการจัดการเหตุการณ์เมื่อเกิดขึ้นในภายหลังหลังจากที่สร้างแฮนเดิลแล้ว กลไกการจัดการเหตุการณ์จะส่งแฮนเดิลและคุกกี้ของแฮนเดิลกลับไปยังตัวจัดการเหตุการณ์
คุณสามารถรอเหตุการณ์โดยใช้การเรียก wait()
wait()
รอให้เหตุการณ์เกิดขึ้นในแฮนเดิลที่ระบุเป็นระยะเวลาที่กําหนด
long wait(uint32_t handle_id, uevent_t *event, unsigned long timeout_msecs)
[in] handle_id
: แฮนเดิลที่การเรียก API ใดเรียกให้แสดง
[out] event
: ตัวชี้ไปยังโครงสร้างที่แสดงถึงเหตุการณ์ที่เกิดขึ้นในแฮนเดิลนี้
[in] timeout_msecs
: ค่าการหมดเวลาเป็นมิลลิวินาที ค่า -1 หมายถึงการหมดเวลาแบบไม่จำกัด
[retval]: NO_ERROR
หากเหตุการณ์ที่ถูกต้องเกิดขึ้นภายในช่วงเวลาหมดเวลาที่ระบุ ERR_TIMED_OUT
หากหมดเวลาตามที่ระบุแล้ว แต่ไม่มีเหตุการณ์เกิดขึ้น < 0
สำหรับข้อผิดพลาดอื่นๆ
เมื่อดำเนินการสำเร็จ (retval == NO_ERROR
) การเรียก wait()
จะเติมโครงสร้าง uevent_t
ที่ระบุด้วยข้อมูลเกี่ยวกับเหตุการณ์ที่เกิดขึ้น
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
มีชุดค่าผสมต่อไปนี้
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
- ไม่มีเหตุการณ์ที่รอดำเนินการจริง ๆ ผู้โทรควรเริ่มการรอใหม่
IPC_HANDLE_POLL_ERROR
- เกิดข้อผิดพลาดภายในที่ไม่ได้ระบุ
IPC_HANDLE_POLL_READY
- ขึ้นอยู่กับประเภทแฮนเดิล ดังนี้
- สําหรับพอร์ต ค่านี้จะระบุว่ามีการเชื่อมต่อที่รอดำเนินการ
- สำหรับแชแนล ค่านี้บ่งบอกว่ามีการสร้างการเชื่อมต่อแบบไม่ประสานเวลา (ดู
connect()
)
เหตุการณ์ต่อไปนี้เกี่ยวข้องกับช่องเท่านั้น
IPC_HANDLE_POLL_HUP
- ระบุว่าช่องถูกปิดโดยบุคคลอื่นIPC_HANDLE_POLL_MSG
- บ่งบอกว่ามีข้อความที่รอดำเนินการสำหรับช่องนี้IPC_HANDLE_POLL_SEND_UNBLOCKED
- บ่งบอกว่าผู้โทรที่ก่อนหน้านี้ถูกบล็อกไม่ให้ส่งข้อความอาจพยายามส่งข้อความอีกครั้ง (ดูรายละเอียดของsend_msg()
)
ควรเตรียมตัวให้พร้อมสำหรับตัวแฮนเดิลเหตุการณ์เพื่อจัดการชุดค่าผสมของเหตุการณ์ที่ระบุ เนื่องจากอาจมีการตั้งค่าหลายบิตพร้อมกัน ตัวอย่างเช่น แชแนลหนึ่งอาจมีข้อความที่รอดำเนินการและการเชื่อมต่อที่ปิดโดยพาร์ทเนอร์พร้อมกัน
เหตุการณ์ส่วนใหญ่จะติดอยู่ โดยจะยังคงอยู่ตราบใดที่เงื่อนไขพื้นฐานยังคงอยู่ (เช่น ได้รับข้อความที่รอดำเนินการทั้งหมดและจัดการคําขอการเชื่อมต่อที่รอดําเนินการ) ยกเว้นในกรณีที่มีเหตุการณ์ IPC_HANDLE_POLL_SEND_UNBLOCKED
ซึ่งจะล้างออกเมื่ออ่าน และแอปมีเพียง 1 โอกาสในการจัดการ
คุณทำลายแฮนเดิลได้โดยเรียกใช้เมธอด close()
close()
ทำลายทรัพยากรที่เชื่อมโยงกับแฮนเดิลที่ระบุและนำออกจากตารางแฮนเดิล
long close(uint32_t handle_id);
[in] handle_id
: แฮนเดิลสำหรับทำลาย
[retval]: 0 หากสําเร็จ หากไม่สําเร็จจะเป็นค่าลบ
Server API
เซิร์ฟเวอร์จะเริ่มด้วยการสร้างพอร์ตที่มีชื่ออย่างน้อย 1 พอร์ต ซึ่งแสดงถึงปลายทางบริการ พอร์ตแต่ละพอร์ตจะแสดงด้วยแฮนเดิล
เมธอดใน Server API
port_create()
สร้างพอร์ตบริการที่มีชื่อ
long port_create (const char *path, uint num_recv_bufs, size_t recv_buf_size, uint32_t flags)
[in] path
: ชื่อสตริงของพอร์ต (ตามที่อธิบายไว้ข้างต้น) ชื่อนี้ควรไม่ซ้ำกันทั่วทั้งระบบ การสร้างชื่อที่ซ้ำกันจะไม่สำเร็จ
[in] num_recv_bufs
: จํานวนบัฟเฟอร์สูงสุดที่แชแนลในพอร์ตนี้สามารถจัดสรรล่วงหน้าเพื่ออำนวยความสะดวกในการแลกเปลี่ยนข้อมูลกับไคลเอ็นต์ ระบบจะนับบัฟเฟอร์แยกกันสำหรับข้อมูลที่ส่งและรับในทั้ง 2 ทิศทาง ดังนั้นการระบุ 1 ที่นี่จะหมายถึงมีการจองบัฟเฟอร์การส่ง 1 รายการและบัฟเฟอร์การรับ 1 รายการไว้ล่วงหน้า โดยทั่วไปแล้ว จำนวนบัฟเฟอร์ที่จําเป็นจะขึ้นอยู่กับข้อตกลงโปรโตคอลระดับที่สูงขึ้นระหว่างไคลเอ็นต์กับเซิร์ฟเวอร์ ตัวเลขนี้อาจเป็นเพียง 1 ในกรณีของโปรโตคอลแบบซิงค์กันมาก (ส่งข้อความ รับการตอบกลับก่อนที่จะส่งข้อความอื่น) แต่จำนวนนี้อาจมากกว่าได้หากไคลเอ็นต์คาดว่าจะส่งข้อความมากกว่า 1 รายการก่อนที่การตอบกลับจะปรากฏขึ้น (เช่น ข้อความ 1 รายการเป็นคำนำและอีกข้อความเป็นคำสั่งจริง) ชุดบัฟเฟอร์ที่จัดสรรจะจัดสรรตามช่อง ดังนั้นการเชื่อมต่อ (ช่อง) 2 ช่องแยกกันจะมีชุดบัฟเฟอร์แยกกัน
[in] recv_buf_size
: ขนาดสูงสุดของบัฟเฟอร์แต่ละรายการในชุดบัฟเฟอร์ข้างต้น ค่านี้ขึ้นอยู่กับโปรโตคอลและจำกัดขนาดข้อความสูงสุดที่คุณสามารถแลกเปลี่ยนกับคู่สนทนาได้อย่างมีประสิทธิภาพ
[in] flags
: ชุดค่าผสมของ Flag ที่ระบุลักษณะการทํางานเพิ่มเติมของพอร์ต
ค่านี้ควรเป็นชุดค่าผสมของค่าต่อไปนี้
IPC_PORT_ALLOW_TA_CONNECT
- อนุญาตการเชื่อมต่อจากแอปที่ปลอดภัยอื่นๆ
IPC_PORT_ALLOW_NS_CONNECT
- อนุญาตการเชื่อมต่อจากโลกที่ไม่ปลอดภัย
[retval]: แฮนเดิลของพอร์ตที่สร้างหากไม่ใช่ค่าลบ หรือข้อผิดพลาดที่เฉพาะเจาะจงหากเป็นค่าลบ
จากนั้นเซิร์ฟเวอร์จะตรวจสอบรายการแฮนเดิลพอร์ตเพื่อหาการเชื่อมต่อขาเข้าโดยใช้การเรียก wait()
เมื่อได้รับคำขอเชื่อมต่อที่ระบุโดยบิต IPC_HANDLE_POLL_READY
ที่กําหนดไว้ในช่อง event
ของโครงสร้าง uevent_t
เซิร์ฟเวอร์ควรเรียกใช้ accept()
เพื่อเชื่อมต่อให้เสร็จสมบูรณ์และสร้างแชแนล (แสดงโดยแฮนเดิลอื่น) ซึ่งจะทำการสำรวจหาข้อความขาเข้าได้
accept()
ยอมรับการเชื่อมต่อขาเข้าและรับแฮนเดิลของช่อง
long accept(uint32_t handle_id, uuid_t *peer_uuid);
[in] handle_id
: แฮนเดิลที่แสดงพอร์ตที่ไคลเอ็นต์เชื่อมต่ออยู่
[out] peer_uuid
: ตัวชี้ไปยังโครงสร้าง uuid_t
เพื่อป้อน UUID ของแอปไคลเอ็นต์ที่เชื่อมต่อ ระบบจะตั้งค่าเป็น 0 ทั้งหมดหากการเชื่อมต่อมาจากโลกที่ไม่ปลอดภัย
[retval]: แฮนเดิลของแชแนล (หากไม่ใช่ค่าลบ) ที่เซิร์ฟเวอร์สามารถแลกเปลี่ยนข้อความกับไคลเอ็นต์ได้ (หรือรหัสข้อผิดพลาด)
Client API
ส่วนนี้มีเมธอดใน Client API
เมธอดใน Client API
connect()
เริ่มการเชื่อมต่อกับพอร์ตที่ระบุด้วยชื่อ
long connect(const char *path, uint flags);
[in] path
: ชื่อพอร์ตที่เผยแพร่โดยแอปที่เชื่อถือได้
[in] flags
: ระบุลักษณะการทำงานเพิ่มเติมที่ไม่บังคับ
[retval]: แฮนเดิลของแชแนลที่ใช้แลกเปลี่ยนข้อความกับเซิร์ฟเวอร์ได้ แสดงข้อผิดพลาดหากเป็นค่าลบ
หากไม่ได้ระบุ flags
(มีการตั้งค่าพารามิเตอร์ flags
เป็น 0) การเรียกใช้ connect()
จะเริ่มต้นการเชื่อมต่อแบบซิงค์กับพอร์ตที่ระบุ ซึ่งจะแสดงข้อผิดพลาดทันทีหากไม่มีพอร์ตนั้น และสร้างบล็อกจนกว่าเซิร์ฟเวอร์จะยอมรับการเชื่อมต่อ
คุณเปลี่ยนลักษณะการทํางานนี้ได้โดยระบุค่า 2 ค่าร่วมกันตามที่อธิบายไว้ด้านล่าง
enum { IPC_CONNECT_WAIT_FOR_PORT = 0x1, IPC_CONNECT_ASYNC = 0x2, };
IPC_CONNECT_WAIT_FOR_PORT
- บังคับให้connect()
การเรียกใช้รอหากพอร์ตที่ระบุไม่อยู่ในการเรียกใช้ทันทีแทนที่จะดำเนินการไม่สำเร็จทันที
IPC_CONNECT_ASYNC
- หากตั้งค่าไว้ ระบบจะเริ่มการเชื่อมต่อแบบไม่พร้อมกัน แอปต้องตรวจสอบหาตัวแฮนเดิลที่แสดงผลโดยเรียกใช้ wait()
เพื่อดูเหตุการณ์การเชื่อมต่อที่เสร็จสมบูรณ์ซึ่งระบุโดยบิต IPC_HANDLE_POLL_READY
ที่กําหนดไว้ในช่องเหตุการณ์ของโครงสร้าง uevent_t
ก่อนเริ่มการทํางานตามปกติ
Messaging API
การเรียก Messaging API ช่วยให้สามารถส่งและอ่านข้อความผ่านการเชื่อมต่อ (แชแนล) ที่ตั้งไว้ก่อนหน้านี้ การเรียก Messaging API จะเหมือนกันสำหรับเซิร์ฟเวอร์และไคลเอ็นต์
ไคลเอ็นต์จะได้รับแฮนเดิลของช่องโดยการเรียกใช้connect()
และเซิร์ฟเวอร์จะได้รับแฮนเดิลของช่องจากการเรียกใช้ accept()
ตามที่อธิบายไว้ข้างต้น
โครงสร้างของข้อความที่เชื่อถือได้
ดังที่แสดงต่อไปนี้ ข้อความที่ Trusty API แลกเปลี่ยนกันจะมีโครงสร้างน้อยที่สุด โดยปล่อยให้เซิร์ฟเวอร์และไคลเอ็นต์ตกลงกันเรื่องความหมายของเนื้อหาจริง
/* * 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;
ข้อความอาจประกอบด้วยบัฟเฟอร์ที่ไม่ต่อเนื่องอย่างน้อย 1 รายการที่แสดงโดยอาร์เรย์ของโครงสร้าง iovec_t
Trusty จะทำการกระจายรวบรวมข้อมูลอ่านและเขียนลงในบล็อกเหล่านี้โดยใช้อาร์เรย์ iov
เนื้อหาของบัฟเฟอร์ที่อธิบายได้ด้วยอาร์เรย์ iov
นั้นขึ้นอยู่กับผู้ใช้
เมธอดใน Messaging API
send_msg()
ส่งข้อความผ่านช่องทางที่ระบุ
long send_msg(uint32_t handle, ipc_msg_t *msg);
[in] handle
: แฮนเดิลของช่องที่จะส่งข้อความ
[in] msg
: ตัวชี้ไปยัง ipc_msg_t structure
ที่อธิบายข้อความ
[retval]: จํานวนไบต์ทั้งหมดที่ส่งเมื่อสําเร็จ หากไม่สําเร็จจะเป็นค่าลบ
หากไคลเอ็นต์ (หรือเซิร์ฟเวอร์) พยายามส่งข้อความผ่านแชแนลและไม่มีที่ว่างในคิวข้อความของคู่ปลายทาง แชแนลอาจเข้าสู่สถานะการส่งถูกบล็อก (ซึ่งไม่ควรเกิดขึ้นกับโปรโตคอลคำขอ/ตอบแบบซิงค์ที่เรียบง่าย แต่อาจเกิดขึ้นในกรณีที่ซับซ้อนมากขึ้น) ซึ่งจะแสดงโดยการส่งรหัสข้อผิดพลาด ERR_NOT_ENOUGH_BUFFER
ในกรณีเช่นนี้ ผู้เรียกต้องรอจนกว่าพาร์ทเนอร์จะเพิ่มพื้นที่ว่างในคิวรับโดยดึงข้อมูลการจัดการและข้อความที่เลิกใช้งาน ซึ่งระบุโดยบิต IPC_HANDLE_POLL_SEND_UNBLOCKED
ที่กําหนดไว้ในช่อง event
ของโครงสร้าง uevent_t
ที่การเรียก wait()
แสดงผล
get_msg()
รับข้อมูลเมตาเกี่ยวกับข้อความถัดไปในคิวข้อความขาเข้า
ของช่องที่ระบุ
long get_msg(uint32_t handle, ipc_msg_info_t *msg_info);
[in] handle
: แฮนเดิลของช่องที่ต้องดึงข้อมูลข้อความใหม่
[out] msg_info
: โครงสร้างข้อมูลข้อความที่อธิบายไว้ดังนี้
typedef struct ipc_msg_info { size_t len; /* total message length */ uint32_t id; /* message id */ } ipc_msg_info_t;
แต่ละข้อความจะได้รับรหัสที่ไม่ซ้ำกันจากชุดข้อความที่รอดำเนินการ และระบบจะกรอกความยาวทั้งหมดของข้อความแต่ละรายการ หากมีการกําหนดค่าและโปรโตคอลอนุญาต ช่องหนึ่งๆ อาจมีข้อความที่รอดําเนินการ (เปิดอยู่) หลายรายการพร้อมกันได้
[retval]: NO_ERROR
หากสำเร็จ หรือข้อผิดพลาดเชิงลบหากไม่สำเร็จ
read_msg()
อ่านเนื้อหาของข้อความที่มีรหัสที่ระบุโดยเริ่มจากออฟเซตที่ระบุ
long read_msg(uint32_t handle, uint32_t msg_id, uint32_t offset, ipc_msg_t *msg);
[in] handle
: แฮนเดิลของช่องที่จะอ่านข้อความ
[in] msg_id
: รหัสของข้อความที่จะอ่าน
[in] offset
: ส่วนเพิ่มในข้อความที่จะเริ่มต้นอ่าน
[out] msg
: ตัวชี้ไปยังโครงสร้าง ipc_msg_t
ที่อธิบายชุดบัฟเฟอร์สำหรับจัดเก็บข้อมูลข้อความขาเข้า
[retval]: จํานวนไบต์ทั้งหมดที่จัดเก็บไว้ในบัฟเฟอร์ msg
เมื่อดำเนินการสำเร็จ หากไม่สำเร็จ ระบบจะแสดงข้อผิดพลาดเชิงลบ
เรียกเมธอด read_msg
ได้หลายครั้งโดยเริ่มจากออฟเซตอื่น (ไม่จำเป็นต้องเรียงตามลำดับ) ตามต้องการ
put_msg()
เลิกใช้งานข้อความที่มีรหัสที่ระบุ
long put_msg(uint32_t handle, uint32_t msg_id);
[in] handle
: แฮนเดิลของช่องที่ได้รับข้อความ
[in] msg_id
: รหัสของข้อความที่จะเลิกใช้งาน
[retval]: NO_ERROR
หากสำเร็จ หรือข้อผิดพลาดเชิงลบหากไม่สำเร็จ
คุณจะเข้าถึงเนื้อหาข้อความไม่ได้หลังจากที่ข้อความถูกนำออกแล้ว และมีการปล่อยบัฟเฟอร์ที่ข้อความนั้นใช้อยู่
File Descriptor API
File Descriptor API มีการเรียก read()
, write()
และ ioctl()
การเรียกใช้ทั้งหมดเหล่านี้สามารถทํางานกับชุดตัวบ่งชี้ไฟล์ (แบบคงที่) ที่กําหนดไว้ล่วงหน้า ซึ่งตามปกติจะแสดงด้วยตัวเลขเล็กๆ ในการใช้งานปัจจุบัน พื้นที่ตัวระบุไฟล์จะแยกจากพื้นที่แฮนเดิล IPC File Descriptor API ใน Trusty จะคล้ายกับ API แบบดั้งเดิมที่ใช้ File Descriptor
โดยค่าเริ่มต้นจะมีตัวระบุไฟล์ (มาตรฐานและที่รู้จักกันดี) ที่กําหนดไว้ล่วงหน้า 3 รายการ ดังนี้
- 0 - อินพุตมาตรฐาน การใช้งานเริ่มต้นของอินพุตมาตรฐาน
fd
จะเป็นการดำเนินการที่ไม่มีผล (เนื่องจากแอปที่เชื่อถือได้ไม่ควรมีคอนโซลแบบอินเทอร์แอกทีฟ) ดังนั้นการอ่าน การเขียน หรือเรียกใช้ioctl()
ในfd
0 ควรแสดงข้อผิดพลาดERR_NOT_SUPPORTED
- 1 - เอาต์พุตมาตรฐาน ระบบสามารถกำหนดเส้นทางข้อมูลที่เขียนไปยังเอาต์พุตมาตรฐาน (ขึ้นอยู่กับระดับการแก้ไขข้อบกพร่องของ LK) ไปยัง UART และ/หรือบันทึกหน่วยความจำที่มีอยู่ในฝั่งที่ไม่ปลอดภัย ทั้งนี้ขึ้นอยู่กับแพลตฟอร์มและการกำหนดค่า บันทึกการแก้ไขข้อบกพร่องและข้อความที่ไม่ร้ายแรงควรอยู่ในเอาต์พุตมาตรฐาน เมธอด
read()
และioctl()
จะไม่ทํางานและควรแสดงข้อผิดพลาดERR_NOT_SUPPORTED
- 2 - ข้อผิดพลาดมาตรฐาน ข้อมูลที่เขียนไปยังข้อผิดพลาดมาตรฐานควรกำหนดเส้นทางไปยัง UART หรือบันทึกหน่วยความจำที่มีอยู่ในฝั่งที่ไม่ปลอดภัย ทั้งนี้ขึ้นอยู่กับแพลตฟอร์มและการกำหนดค่า ขอแนะนําให้เขียนเฉพาะข้อความสําคัญไปยังมาตรฐานข้อผิดพลาด เนื่องจากสตรีมนี้มีแนวโน้มที่จะไม่มีการจํากัดอย่างมาก เมธอด
read()
และioctl()
จะไม่ทําการใดๆ และควรแสดงข้อผิดพลาดERR_NOT_SUPPORTED
แม้ว่าชุดตัวระบุไฟล์นี้จะขยายเพื่อใช้งานเพิ่มเติมได้fds
(เพื่อใช้งานส่วนขยายเฉพาะแพลตฟอร์ม) แต่คุณควรใช้ตัวระบุไฟล์แบบขยายด้วยความระมัดระวัง การขยายตัวบ่งชี้ไฟล์มีแนวโน้มที่จะทำให้เกิดข้อขัดแย้ง และโดยทั่วไปเราไม่แนะนําให้ทำ
เมธอดใน File Descriptor API
read()
พยายามอ่านข้อมูลสูงสุด count
ไบต์จากตัวระบุไฟล์ที่ระบุ
long read(uint32_t fd, void *buf, uint32_t count);
[in] fd
: ตัวบอกไฟล์ที่จะอ่าน
[out] buf
: ตัวชี้ไปยังบัฟเฟอร์ที่จะจัดเก็บข้อมูล
[in] count
: จํานวนไบต์สูงสุดที่จะอ่าน
[retval]: จำนวนไบต์ที่อ่านได้ หากไม่สำเร็จ ระบบจะแสดงข้อผิดพลาดเชิงลบ
write()
เขียนข้อมูลสูงสุด count
ไบต์ไปยังตัวระบุไฟล์ที่ระบุ
long write(uint32_t fd, void *buf, uint32_t count);
[in] fd
: ตัวระบุไฟล์ที่จะเขียน
[out] buf
: ตัวชี้ไปยังข้อมูลที่จะเขียน
[in] count
: จํานวนไบต์สูงสุดที่จะเขียน
[retval]: จำนวนไบต์ที่เขียนแล้วที่แสดงผล หากไม่แสดงผล ระบบจะแสดงข้อผิดพลาดเชิงลบ
ioctl()
เรียกใช้คำสั่ง ioctl
ที่ระบุสำหรับตัวระบุไฟล์ที่ระบุ
long ioctl(uint32_t fd, uint32_t cmd, void *args);
[in] fd
: ตัวระบุไฟล์ที่จะเรียกใช้ ioctl()
[in] cmd
: คำสั่ง ioctl
[เข้า/ออก] args
: ตัวชี้ไปยังอาร์กิวเมนต์ ioctl()
API อื่นๆ
เมธอดใน Miscellaneous API
gettime()
แสดงเวลาปัจจุบันของระบบ (เป็นนาโนวินาที)
long gettime(uint32_t clock_id, uint32_t flags, int64_t *time);
[in] clock_id
: ขึ้นอยู่กับแพลตฟอร์ม ให้ส่งค่า 0 เป็นค่าเริ่มต้น
[in] flags
: สงวนไว้ ควรเป็น 0
[out] time
: ตัวชี้ไปยังค่า int64_t
สำหรับจัดเก็บเวลาปัจจุบัน
[retval]: NO_ERROR
หากสำเร็จ หรือข้อผิดพลาดเชิงลบหากไม่สำเร็จ
nanosleep()
ระงับการเรียกใช้แอปการโทรเป็นระยะเวลาหนึ่งตามที่ระบุไว้ และกลับมาทำงานต่อหลังจากระยะเวลาดังกล่าว
long nanosleep(uint32_t clock_id, uint32_t flags, uint64_t sleep_time)
[in] clock_id
: สงวนไว้ ควรเป็น 0
[in] flags
: สงวนไว้ ควรเป็น 0
[in] sleep_time
: เวลาพักเป็นนาโนวินาที
[retval]: NO_ERROR
หากสำเร็จ หรือข้อผิดพลาดเชิงลบหากไม่สำเร็จ
ตัวอย่างเซิร์ฟเวอร์แอปที่เชื่อถือได้
แอปตัวอย่างต่อไปนี้แสดงการใช้งาน API ข้างต้น ตัวอย่างนี้จะสร้างบริการ "echo" ที่จัดการการเชื่อมต่อขาเข้าหลายรายการ และแสดงข้อความทั้งหมดที่ได้รับจากไคลเอ็นต์ซึ่งมาจากฝั่งที่ปลอดภัยหรือไม่ปลอดภัยกลับไปยังผู้เรียก
#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 app 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()
จะส่งข้อความ 10,000 รายการแบบไม่พร้อมกันไปยังบริการ "echo" และจัดการการตอบกลับ
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; }
API และแอปที่ไม่ปลอดภัย
ชุดบริการที่เชื่อถือได้ซึ่งเผยแพร่จากฝั่งที่ปลอดภัยและทําเครื่องหมายด้วยแอตทริบิวต์ IPC_PORT_ALLOW_NS_CONNECT
จะเข้าถึงเคอร์เนลและโปรแกรมสเปซผู้ใช้ที่ทํางานในฝั่งที่ไม่ปลอดภัยได้
สภาพแวดล้อมการดําเนินการในด้านที่ไม่ปลอดภัย (เคอร์เนลและพื้นที่ผู้ใช้) จะแตกต่างจากสภาพแวดล้อมการดําเนินการในด้านที่ปลอดภัยอย่างมาก ดังนั้นจึงมี API 2 ชุดที่แตกต่างกันแทนที่จะเป็นไลบรารีเดียวสำหรับทั้ง 2 สภาพแวดล้อม ในเคอร์เนล Client API จะมาจากไดรเวอร์เคอร์เนล trusty-ipc และลงทะเบียนโหนดอุปกรณ์แบบอักขระที่กระบวนการในพื้นที่ผู้ใช้สามารถใช้เพื่อสื่อสารกับบริการที่ทำงานในด้านที่ปลอดภัย
User space Trusty IPC Client API
ไลบรารี Trusty IPC Client API ในพื้นที่ผู้ใช้เป็นเลเยอร์บางๆ ที่อยู่ด้านบนของโหนดอุปกรณ์ fd
โปรแกรมพื้นที่ผู้ใช้เริ่มเซสชันการสื่อสารโดยเรียกใช้ tipc_connect()
เพื่อเริ่มต้นการเชื่อมต่อกับบริการ Trusty ที่ระบุ การทำงานภายในคือการเรียก tipc_connect()
จะเปิดโหนดอุปกรณ์ที่ระบุเพื่อรับตัวระบุไฟล์ และเรียกใช้การเรียก TIPC_IOC_CONNECT ioctl()
ด้วยพารามิเตอร์ argp
ที่ชี้ไปยังสตริงที่มีชื่อบริการที่จะเชื่อมต่อ
#define TIPC_IOC_MAGIC 'r' #define TIPC_IOC_CONNECT _IOW(TIPC_IOC_MAGIC, 0x80, char *)
ตัวระบุไฟล์ที่ได้จะใช้เพื่อสื่อสารกับบริการที่สร้างตัวระบุไฟล์นั้นเท่านั้น คุณควรปิดตัวระบุไฟล์โดยเรียกใช้ tipc_close()
เมื่อไม่จำเป็นต้องใช้การเชื่อมต่ออีกต่อไป
ตัวระบุไฟล์ที่ได้จากการเรียกใช้ tipc_connect()
จะทํางานเป็นโหนดอุปกรณ์แบบอักขระทั่วไป โดยตัวระบุไฟล์จะมีลักษณะดังนี้
- เปลี่ยนเป็นโหมดที่ไม่มีการบล็อกได้หากจำเป็น
- สามารถเขียนโดยใช้การเรียก
write()
แบบมาตรฐานเพื่อส่งข้อความไปยังอีกฝั่ง - ทำการสำรวจได้ (โดยใช้การเรียก
poll()
หรือselect()
) เพื่อดูความพร้อมของข้อความขาเข้าในฐานะตัวระบุไฟล์ปกติ - อ่านเพื่อดึงข้อมูลข้อความขาเข้าได้
ผู้โทรส่งข้อความไปยังบริการ Trusty โดยการเรียกใช้การเขียนสำหรับ fd
ที่ระบุ ข้อมูลทั้งหมดที่ส่งไปยังwrite()
callข้างต้นจะเปลี่ยนรูปแบบเป็นข้อความโดยไดรเวอร์ trusty-ipc ระบบจะส่งข้อความไปยังฝั่งที่ปลอดภัยซึ่งข้อมูลจะได้รับการจัดการโดยระบบย่อย IPC ในเคอร์เนล Trusty และส่งไปยังปลายทางที่เหมาะสม รวมถึงส่งไปยังลูปเหตุการณ์ของแอปเป็นเหตุการณ์ IPC_HANDLE_POLL_MSG
ในตัวแฮนเดิลแชแนลหนึ่งๆ บริการ Trusty อาจส่งข้อความตอบกลับอย่างน้อย 1 รายการที่ส่งกลับไปยังฝั่งที่ไม่ปลอดภัยและวางไว้ในคิวข้อความตัวระบุไฟล์ของแชแนลที่เหมาะสมเพื่อให้แอปพื้นที่ทำงานของผู้ใช้เรียกread()
ใช้
tipc_connect()
เปิดโหนดอุปกรณ์ tipc
ที่ระบุและเริ่มการเชื่อมต่อกับบริการ Trusty ที่ระบุ
int tipc_connect(const char *dev_name, const char *srv_name);
[in] dev_name
: เส้นทางไปยังโหนดอุปกรณ์ Trusty IPC ที่เปิด
[in] srv_name
: ชื่อบริการ Trusty ที่เผยแพร่ซึ่งจะเชื่อมต่อ
[retval]: ตัวระบุไฟล์ที่ถูกต้องหากดำเนินการสำเร็จ หรือ -1 หากไม่สำเร็จ
tipc_close()
ปิดการเชื่อมต่อกับบริการ Trusty ที่ระบุโดยตัวระบุไฟล์
int tipc_close(int fd);
[in] fd
: ตัวระบุไฟล์ที่เปิดก่อนหน้านี้โดยเรียกใช้ tipc_connect()
Kernel Trusty IPC Client API
Trusty IPC Client API ของเคอร์เนลพร้อมใช้งานสำหรับไดรเวอร์เคอร์เนล ระบบจะใช้ Trusty IPC API ของพื้นที่ผู้ใช้บน API นี้
โดยทั่วไป การใช้งานทั่วไปของ API นี้ประกอบด้วยผู้เรียกที่สร้างออบเจ็กต์ struct tipc_chan
โดยใช้ฟังก์ชัน tipc_create_channel()
จากนั้นใช้การเรียก tipc_chan_connect()
เพื่อเริ่มต้นการเชื่อมต่อกับบริการ Trusty IPC ที่ทำงานในด้านที่ปลอดภัย คุณสามารถสิ้นสุดการเชื่อมต่อกับฝั่งระยะไกลได้โดยเรียกใช้ tipc_chan_shutdown()
ตามด้วย tipc_chan_destroy()
เพื่อล้างทรัพยากร
เมื่อได้รับการแจ้งเตือน (ผ่านhandle_event()
การติดต่อกลับ)
ว่าการเชื่อมต่อสําเร็จแล้ว ผู้โทรจะทำดังนี้
- รับบัฟเฟอร์ข้อความโดยใช้การเรียก
tipc_chan_get_txbuf_timeout()
- เขียนข้อความ และ
- จัดคิวข้อความโดยใช้
tipc_chan_queue_msg()
วิธีนี้เพื่อนำส่งไปยังบริการที่เชื่อถือได้ (ฝั่งที่ปลอดภัย) ซึ่งเชื่อมต่อกับแชแนล
หลังจากจัดคิวเรียบร้อยแล้ว ผู้เรียกใช้ไม่ควรสนใจบัฟเฟอร์ข้อความเนื่องจากบัฟเฟอร์ข้อความจะกลับไปที่พูลบัฟเฟอร์ว่างในท้ายที่สุดหลังจากประมวลผลโดยฝั่งระยะไกล (เพื่อใช้ซ้ำในภายหลังสำหรับข้อความอื่นๆ) ผู้ใช้ต้องเรียกใช้ tipc_chan_put_txbuf()
เฉพาะในกรณีที่จัดคิวบัฟเฟอร์ดังกล่าวไม่สำเร็จหรือไม่จําเป็นต้องใช้อีกต่อไป
ผู้ใช้ API จะได้รับข้อความจากฝั่งระยะไกลโดยการจัดการการเรียกกลับhandle_msg()
การแจ้งเตือน (ซึ่งเรียกใช้ในบริบทของ workqueue rx
ของ trusty-ipc) ที่ให้พอยน์เตอร์ไปยังบัฟเฟอร์ rx
ที่มีข้อความขาเข้าที่จะจัดการ
การติดตั้งใช้งาน handle_msg()
callback ควรแสดงผลพอยน์เตอร์ไปยัง struct tipc_msg_buf
ที่ถูกต้อง
ซึ่งอาจเป็นบัฟเฟอร์ข้อความขาเข้าได้หากจัดการในเครื่องและไม่จำเป็นต้องใช้อีกต่อไป หรืออาจเป็นบัฟเฟอร์ใหม่ที่ได้รับจากtipc_chan_get_rxbuf()
call หากบัฟเฟอร์ขาเข้าอยู่ในคิวเพื่อประมวลผลเพิ่มเติม คุณต้องติดตามบัฟเฟอร์ rx
ที่แยกออก และปล่อยบัฟเฟอร์ดังกล่าวเมื่อไม่จําเป็นต้องใช้แล้วโดยใช้การเรียก tipc_chan_put_rxbuf()
เมธอดใน Kernel Trusty IPC Client API
tipc_create_channel()
สร้างและกําหนดค่าอินสแตนซ์ของแชแนล Trusty IPC สําหรับอุปกรณ์ trusty-ipc เครื่องหนึ่งๆ
struct tipc_chan *tipc_create_channel(struct device *dev, const struct tipc_chan_ops *ops, void *cb_arg);
[in] dev
: ตัวชี้ไปยัง trusty-ipc ที่สร้างขึ้นสำหรับแชแนลอุปกรณ์
[in] ops
: ชี้ไปยัง struct tipc_chan_ops
ที่มีข้อมูลการเรียกกลับเฉพาะผู้โทร
[in] cb_arg
: ตัวชี้ไปยังข้อมูลที่ส่งไปยังการเรียกกลับ tipc_chan_ops
[retval]: ชี้ไปยังอินสแตนซ์ของ struct tipc_chan
ที่สร้างขึ้นใหม่หากสําเร็จ หรือ ERR_PTR(err)
หากไม่สําเร็จ
โดยทั่วไป ผู้เรียกต้องระบุการเรียกกลับ 2 รายการที่เรียกใช้แบบไม่พร้อมกันเมื่อกิจกรรมที่เกี่ยวข้องเกิดขึ้น
void (*handle_event)(void *cb_arg, int event)
มีการเรียกเหตุการณ์เพื่อแจ้งเตือนผู้โทรเกี่ยวกับการเปลี่ยนแปลงสถานะของช่อง
[in] cb_arg
: ตัวชี้ไปยังข้อมูลที่ส่งไปยังการเรียกใช้ tipc_create_channel()
[in] event
: เหตุการณ์ที่มีค่าใดค่าหนึ่งต่อไปนี้
TIPC_CHANNEL_CONNECTED
- บ่งบอกว่าเชื่อมต่อกับฝั่งระยะไกลสำเร็จTIPC_CHANNEL_DISCONNECTED
- ระบุว่าฝั่งระยะไกลปฏิเสธคำขอเชื่อมต่อใหม่หรือขอยกเลิกการเชื่อมต่อสำหรับแชแนลที่เชื่อมต่อไว้ก่อนหน้านี้TIPC_CHANNEL_SHUTDOWN
- ระบุว่าฝั่งระยะไกลกำลังปิดระบบ ซึ่งจะสิ้นสุดการเชื่อมต่อทั้งหมดอย่างถาวร
ระบบจะเรียกใช้ struct tipc_msg_buf *(*handle_msg)(void *cb_arg, struct tipc_msg_buf *mb)
callback เพื่อแจ้งเตือนว่าได้รับข้อความใหม่ผ่านช่องทางที่ระบุ
- [in]
cb_arg
: ตัวชี้ไปยังข้อมูลที่ส่งไปยังการเรียกใช้tipc_create_channel()
- [in]
mb
: ชี้ไปยังstruct tipc_msg_buf
ที่อธิบายข้อความขาเข้า - [retval]: การใช้งานการเรียกกลับควรแสดงผลพอยน์เตอร์ไปยัง
struct tipc_msg_buf
ซึ่งอาจเป็นพอยน์เตอร์เดียวกับที่ได้รับเป็นพารามิเตอร์mb
หากระบบจัดการข้อความในเครื่องและไม่จำเป็นต้องใช้อีกต่อไป (หรืออาจเป็นบัฟเฟอร์ใหม่ที่ได้รับจากการเรียกtipc_chan_get_rxbuf()
)
tipc_chan_connect()
เริ่มการเชื่อมต่อกับบริการ Trusty IPC ที่ระบุ
int tipc_chan_connect(struct tipc_chan *chan, const char *port);
[in] chan
: ตัวชี้ไปยังแชแนลที่การเรียกใช้ tipc_create_chan()
แสดงผล
[in] port
: ตัวชี้ไปยังสตริงที่มีชื่อบริการที่จะเชื่อมต่อ
[retval]: 0 หากสําเร็จ ไม่เช่นนั้นจะเป็นข้อผิดพลาดเชิงลบ
ผู้โทรจะได้รับการแจ้งเตือนเมื่อการเชื่อมต่อเกิดขึ้นโดยได้รับhandle_event
การโทรกลับ
tipc_chan_shutdown()
สิ้นสุดการเชื่อมต่อกับบริการ Trusty IPC ที่เรียกใช้ก่อนหน้านี้โดยtipc_chan_connect()
int tipc_chan_shutdown(struct tipc_chan *chan);
[in] chan
: ตัวชี้ไปยังแชแนลที่การเรียก tipc_create_chan()
แสดงผล
tipc_chan_destroy()
ทำลายช่องทาง IPC ที่เชื่อถือได้ซึ่งระบุ
void tipc_chan_destroy(struct tipc_chan *chan);
[in] chan
: ตัวชี้ไปยังแชแนลที่การเรียกใช้ tipc_create_chan()
แสดงผล
tipc_chan_get_txbuf_timeout()
รับบัฟเฟอร์ข้อความที่ใช้ส่งข้อมูลผ่านแชแนลที่ระบุได้ หากบัฟเฟอร์ไม่พร้อมใช้งานทันที ระบบอาจบล็อกผู้โทรไว้ตามระยะหมดเวลาที่ระบุ (เป็นมิลลิวินาที)
struct tipc_msg_buf * tipc_chan_get_txbuf_timeout(struct tipc_chan *chan, long timeout);
[in] chan
: ตัวชี้ไปยังแชแนลที่จะจัดคิวข้อความ
[in] chan
: ระยะหมดเวลาที่สูงสุดที่จะรอจนกว่าบัฟเฟอร์ tx
จะพร้อมใช้งาน
[retval]: บัฟเฟอร์ข้อความที่ถูกต้องเมื่อดำเนินการสำเร็จ หรือERR_PTR(err)
เมื่อเกิดข้อผิดพลาด
tipc_chan_queue_msg()
จัดคิวข้อความที่จะส่งผ่านแชแนล Trusty IPC ที่ระบุ
int tipc_chan_queue_msg(struct tipc_chan *chan, struct tipc_msg_buf *mb);
[in] chan
: ตัวชี้ไปยังแชแนลที่จะจัดคิวข้อความ
[in] mb:
ตัวชี้ไปยังข้อความที่จะจัดคิว
(รับจากการเรียกใช้ tipc_chan_get_txbuf_timeout()
)
[retval]: 0 หากสําเร็จ ไม่เช่นนั้นจะเป็นข้อผิดพลาดเชิงลบ
tipc_chan_put_txbuf()
ปล่อยบัฟเฟอร์ข้อความ Tx
ที่ระบุซึ่งได้รับก่อนหน้านี้จากการเรียกใช้ tipc_chan_get_txbuf_timeout()
void tipc_chan_put_txbuf(struct tipc_chan *chan, struct tipc_msg_buf *mb);
[in] chan
: ตัวชี้ไปยังแชแนลที่บัฟเฟอร์ข้อความนี้อยู่
[in] mb
: ตัวชี้ไปยังบัฟเฟอร์ข้อความที่จะปล่อย
[retval]: ไม่มี
tipc_chan_get_rxbuf()
รับบัฟเฟอร์ข้อความใหม่ที่ใช้รับข้อความผ่านแชแนลที่ระบุได้
struct tipc_msg_buf *tipc_chan_get_rxbuf(struct tipc_chan *chan);
[in] chan
: ตัวชี้ไปยังช่องที่บัฟเฟอร์ข้อความนี้อยู่
[retval]: บัฟเฟอร์ข้อความที่ถูกต้องเมื่อดำเนินการสำเร็จ ERR_PTR(err)
เมื่อเกิดข้อผิดพลาด
tipc_chan_put_rxbuf()
ปล่อยบัฟเฟอร์ข้อความที่ระบุซึ่งได้รับก่อนหน้านี้จากการเรียกใช้ tipc_chan_get_rxbuf()
void tipc_chan_put_rxbuf(struct tipc_chan *chan, struct tipc_msg_buf *mb);
[in] chan
: ตัวชี้ไปยังช่องที่บัฟเฟอร์ข้อความนี้อยู่
[in] mb
: ตัวชี้ไปยังบัฟเฟอร์ข้อความที่จะปล่อย
[retval]: ไม่มี