LXRT-RTAI用户空间编程_第1页
LXRT-RTAI用户空间编程_第2页
LXRT-RTAI用户空间编程_第3页
LXRT-RTAI用户空间编程_第4页
LXRT-RTAI用户空间编程_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、精品好资料学习推荐LXRTRTAI的用户空间编程目录一.rt_task_init_schmod(启用RTAI实时功能/实时任务的创建)21.函数22.参数23.注意24.示例代码2二.实时任务定时器设置(rt_set_oneshot_mode等)21.rt_set_oneshot_mode32.rt_set_periodic_mode33.start_rt_timer34.注意35.示例代码3三.rt_task_make_periodic(定期运行一个任务)41.函数42.参数43.注意4四.代码基础框架41.Makefile42.run43.runinfo44.代码4五.注意事项71.所谓的

2、LXRT实即Linux Real Time module,不存在LXRT scheduler72.LXRT下的硬实时相对于内核态下而言仍有若干微秒的差别73.在进入和离开LXRT域这两段时间,系统的实时性是无法保证的。74.LXRT Tips And Tricks8六.管道通讯81.发送函数82.接收函数83.示例代码9七.共享内存通讯121.创建函数122.Free函数12一. rt_task_init_schmod(启用RTAI实时功能/实时任务的创建)实时任务的创建主要完成对代表实时任务实体的任务结构变量的初始化操作,包括分配任务栈、初始化任务栈、初始化链表指针等。1. 函数RT_TAS

3、K* rt_task_init(unsigned long name, int priority, int stack_size, int max_msg_size)RT_TASK*rt_task_init_schmod(unsigned long name, int priority, int stack_size, intmax_msg_size, int policy, int cpus_allowed)正如你可以看到的,有两个选项可以用来创建一个用户模式下的实时任务。在用户模式下,rt_task_init被认为是一个更简单但因此有限的捷径。总之他们都可以用于这个特定的目的。只是为了记录

4、第一个被定义为以下的:RTAI_PROTO(RT_TASK *,rt_task_init,(unsigned long name, int priority, int stack_size, int max_msg_size)return rt_task_init_schmod(name, priority, 0, max_msg_size, SCHED_FIFO, 0xFF);它的意思是,它使用SCHED_FIFO策略并且设置cpu允许0XFF。他们创建一个新的实时任务在用户空间,或者更好的说法是,他们在用户空间为LINUX进程/任务创建了一个RTAI任务扩展。2. 参数Name:任务名。P

5、riority:任务优先级,0最高。stack_size:栈大小(不再被使用的遗留参数,只是为了可移植性才保留的)。默认值是512。max_msg_size:可为0,在这种情况下使用一个默认的内部值。默认值为256。为了适合你的需求,有可能需要设置一个更大的值。在这种情况下,要么合理设置宏MSG_SIZE来重新编译sys.c,要么在这里明确分配大点的尺寸。但是,注意这点,消息大小不是关键的。事实上在任何需要的时候,模块都会重新分配它,动态并且设置好了合适的大小。policy:调度策略,默认的是SCHED_FIFO,也可以设置成 RT_SCHED_RR。RR只是在有多个使用相同的优先级并且不释放

6、CPU的任务的时候使用,。在这种情况下,RR政策将会照顾它的平衡cpus_allowed:你想让任务运行的CPU。它是个bit。当RTAI希望一个任务静态地在一个特定的CPU上运行的时候,它是强制性的。注意,如果你想在任务创建之后改变CPU,这一举动将会杀死real_time。如果指定了更多的bit,RTAI通过尽量平衡这工作强迫任务运行在第一个可用的CPU上。/SMP用的3. 注意 消息有个动态内存增加,每次buffer大小溢出时,现有的都会被释放,RTAI real_time heap会新创建一个大约比原来大20%新buffer。这个操作显然是时间消费, 所以为了最好的性能表现,强烈建议从

7、最初始阶段就定义正确的大小。4. 示例代码int main(void)RT_TASK *Main_Task;if (!(Main_Task = rt_task_init_schmod(nam2num(MNTSK), 0, 0, 0, SCHED_FIFO, 0xF) printf(CANNOT INIT MAIN TASKn);exit(1);return 0;二. 实时任务定时器设置(rt_set_oneshot_mode等)在创建实时任务的过程中,主要通过3个函数对定时器进行设置,它们分别是:rt_set_oneshot_mode,rt_set_periodic_mode和start_rt

8、_timer,下面分别对这3个函数进行分析。1. rt_set_oneshot_mode用于将定时器设置为单触发模式,所谓单触发模式,就是说,每当定时器产生一次中断后,系统都要根据目前系统任务对时间精度的要求情况对定时器重新进行编程,设定下一次触发的时间。rt_set_oneshot_mode完成的功能如下:1.调用stop_rt_timer停止定时器的运行;2.设置全局变量oneshot_timer的值为1;在时钟中断函数中,系统会检查oneshot_timer的值,判断定时器的工作模式,然后根据定时器的模式对定时器进行相应的操作。2. rt_set_periodic_modert_set_

9、periodic_mode的操作与rt_set_oneshot_mode的类似,只不过它将oneshot_timer的值设为0,表示定时器应工作在周期模式;当定时器工作在周期模式下时,系统只要对定时器进行一次初始化,指定定时器产生中断的周期,以后就不再需要对定时器进行编程了。3. start_rt_timer根据设定的定时器运行模式对定时器进行初始化,它完成的主要功能如下:1.调用函数rt_request_timer注册时钟中断服务程序rt_timer_handler;2.初始化系统用于保存时间信息的结构rt_smp_times(就是前面所说的rt_times);3.调用rt_request_

10、linux_irq注册一个Linux下的中断服务程序recover_jiffies,这个中断程序和Linux的时钟中断服务程序共享时钟中断,recover_jiffies用于补偿Linux所丢失的时钟中断(因为可能由于实时任务的运行,使Linux很长一段时间得不到运行的机会,无法响应时钟中断)。4. 注意 请注意,如果你不设置模式,默认是周期性的。 使用stop_rt_timer停止定时器,会设置定时器返回默认的状态(即周期性的)。如果没有删除在使用的RTAI调度程序,你想确定在多模块上是单触发模式,在每一个start_rt_timer前总要调用rt_set_oneshot_mode。 使用s

11、tart_rt_timer(0),自动强制进入单触发模式。 rt_is_hard_timer_running API可以知道是否已经有个计时器在运行了,该函数应该小心使用,因为它会形成一个“race”情况。 在使用任何与时间处理相关的函数前调用start_rt_timer API很重要,否则所有的值都被认为是错误的。 实时任务(本文所指的实时任务,如果没有特别说明都是硬实时的)都是以Linux内核模块方式实现的,要实现一个实时任务,在模块初始化的时候要调用RTAI的任务创建函数初始化实时任务相关的数据和环境,指定定时器的运行模式(单触发模式或周期模式),初始化定时器,然后开始执行任务;需要注意

12、的是,当没有加载任何RTAI的实时任务模块的时候,RTAI的任务调度和时钟中断都没有启动。5. 示例代码#define TICK_TIME 1000000if (hard_timer_running = rt_is_hard_timer_running()printf(Skip hard real_timer setting.n);sampling_interval = nano2count(TICK_TIME);elseprintf(Starting real time timer.n);rt_set_oneshot_mode();start_rt_timer(0);sampling_int

13、erval = nano2count(TICK_TIME);三. rt_task_make_periodic(定期运行一个任务)1. 函数在这个阶段,计时器根据定时器政策选择(单触发vs周期)以适当的周期运行,它允许设置一个实时任务定期调度。这可以用以下API实现:Int rt_task_make_periodic (RT_TASK *task, RTIME start_time, RTTIME period);Int rt_task_make_periodic (RT_TASK *task, RTIME start_delay, RTTIME period);2. 参数task任务指针,之前

14、由rt_task_init()创建的,当rt_task_wait_period()被调用时,以period为周期执行。start_time:第一次执行时间,是一个以clock ticks测量的绝对值。start_delay:第一次执行时间,相对于当前时间,以纳秒测量。period:任务循环周期。3. 注意 为了更方便的处理clock ticks和纳秒,在rtai_sched.h中有两个宏定义能帮助你,他们是RTIME count2nano (RTIME timercounts);RTIME nano2count (RTIME nanosecs);,它们只转换时间单位,但是你要记住,计数单位与选

15、择的时间模式(单触发/周期)相关。 Recall that the term clock ticks depends on the mode in which the hard timer runs. So ifthe hard timer was set as periodic a clock tick will last as the period set in start_rt_timer,while if oneshot mode is used a clock tick will last as the inverse of the runningfrequency of the h

16、ard timer in use and irrespective of any period used in the call tostart_rt_timer.四. 代码基础框架前面先准备三个文件:1. MakefileTARGET = periodic_task SRCS = periodic_task.c prefix := $(shell rtai-config -prefix)ifeq ($(prefix),)$(error Please add /bin to your PATH variable)endifOBJECTS = $(SRCS:.c=.o)CC = $(shell

17、rtai-config -cc)LXRT_CFLAGS = $(shell rtai-config -lxrt-cflags)LXRT_LDFLAGS = $(shell rtai-config -lxrt-ldflagsall: $(TARGET)%.o: %.c $(CC) -c $(LXRT_CFLAGS) $(TARGET) : $(OBJECTS) $(CC) -o $(TARGET) $(LXRT_LDFLAGS) -llxrt $(OBJECTS)clean: rm -f *.o * core.* $(TARGET).PHONY: clean2. run实际上是调用rtai-lo

18、ad来运行的.$DESTDIR/usr/realtime/bin/rtai-load3. .runinfo隐藏文件rtai-load根据这个来运行prog_name:lxrt+sem+mbx+msg+fifos:!./prog_name; popall:control_c(2 、3步骤可以简化成另一种方式,直接进入RTAI安装目录,然后insmod rtai_hal.ko insmod rtai_sched.ko insmod rtai_lxrt.ko,然后运行程序./prog_name 就行了)4. 代码 单触发模式#include #include #include #include #i

19、nclude #include #include /#include /#include #include #include #include /#include /#include static int thread0;static void *fun0(void *arg)RT_TASK *task;task = rt_task_init_schmod(nam2num(TASK0), 0, 0, 0, SCHED_FIFO, 0xF); mlockall(MCL_CURRENT | MCL_FUTURE);/设置优先级和调度算法 这里他用SCHED_FIFO,而SCHED_OTHER(基于

20、时间片)优先会低些,这个Name就是实时任务的标识nam2num 是把名字转为name id 以免命名冲突 / 进入硬实时模式,无此语句时,默认的是软实时/rt_make_hard_real_time();/此处添加代码,如下语句/rt_printk(Hello World!n);/将实时任务或者线程返回到标准linux的状态rt_make_soft_real_time();/删除任务rt_task_delete(task); return 0;int main(void) RT_TASK *task; / make main thread LXRT soft realtime task =

21、rt_task_init_schmod(nam2num(MYTASK), 9, 0, 0, SCHED_FIFO, 0xF); mlockall(MCL_CURRENT | MCL_FUTURE); / start realtime timer and scheduler rt_set_oneshot_mode(); start_rt_timer(0); / create a linux thread thread0 = rt_thread_create(fun0, NULL, 10000); / wait for end of program printf(TYPE TO TERMINATE

22、n); getchar(); / cleanup stuff stop_rt_timer(); return 0; 周期模式#include #include #include #include #include #include #include #define TICK_TIME 1000000#define CPUMAP 0x1static RT_TASK *main_Task;static RT_TASK *loop_Task;int keep_on_running = 1;static pthread_t main_thread;static RTIME expected;stati

23、c RTIME sampling_interval;static void *main_loop()if (!(loop_Task = rt_task_init_schmod(nam2num(RTAI01), 2, 0, 0, SCHED_FIFO, CPUMAP) printf(CANNOT INIT PERIODIC TASKn);exit(1);/mlockall(MCL_CURRENT | MCL_FUTURE);(源代码没有,?)expected = rt_get_time() + 100*sampling_interval;rt_task_make_periodic(loop_Ta

24、sk, expected, sampling_interval);/rt_make_hard_real_time();while (keep_on_running)/insert your main periodic loop herert_task_wait_period();/set keep_on_running to 0 if you want to exitrt_task_delete(loop_Task);return 0;int main(void)RT_TASK *Main_Task;if (!(Main_Task = rt_task_init_schmod(nam2num(M

25、NTSK), 0, 0, 0, SCHED_FIFO, 0xF) printf(CANNOT INIT MAIN TASKn);exit(1);/mlockall(MCL_CURRENT | MCL_FUTURE); (源代码没有,?)if (hard_timer_running = rt_is_hard_timer_running()printf(Skip hard real_timer setting.n);sampling_interval = nano2count(TICK_TIME);elseprintf(Starting real time timer.n);rt_set_ones

26、hot_mode();start_rt_timer(0);/启动计时器 记得用完要关掉sampling_interval = nano2count(TICK_TIME);pthread_create(&main_thread, NULL, main_loop, NULL);while (keep_on_running)sampling_interval = sampling_interval; /do nothing!rt_task_delete(Main_Task);return 0;五. 注意事项1. 所谓的LXRT实即Linux Real Time module,不存在LXRT sche

27、duler所谓的LXRT实即Linux Real Time module,不存在LXRT scheduler。RTAI下只有3种调度器,UP,SMP和MUP。LXRT的存在使得RTAI所有的调度函数都能在Linux进程中直接调用。这样一来,RTAI的实时服务就具备了所谓的“完全对称”在RTAI域和LINUX域中的使用几乎完全一样。也就是说,用户可以在LINUX和LINUX间,RTAI和LINUX间共用内存,发送消息,调用semaphore或时间相关服务,当然,在RTAI和RTAI之间更不是问题。(源自DIAPM RTAI - Beginners Guide,https:/www.rtai.or

28、g/index.php?module=documents&JAS_DocumentManager_op=downloadFile&JAS_File_id=32)2. LXRT下的硬实时相对于内核态下而言仍有若干微秒的差别LXRT下的hard real time还是与内核态任务的执行有着本质区别的。RTAI通过其RTAI_PROTO为用户态下进程提供调用内核API的捷径,并由RTAI自身的调度器保证了RTAI任务对中断的优先权。处于中断处理链条终端的LINUX因此不能破坏RTAI任务的实时性能。但无论如何,context switch是需要时间的。在RTAI域内用户态和内核态的切换也免不了牺牲一

29、定的时间开销。RTAI相关的文档指出LXRT下的硬实时相对于内核态下而言仍有若干微秒的差别。笔者也在试验中发现,前者实时性能与后者相比相差约有十几微秒,有时甚至更多。对于一些要求苛刻的实时任务而言,LXRT下的时延(或者还有实时误差?)是无法接受的。3. 在进入和离开LXRT域这两段时间,系统的实时性是无法保证的。也就是说,在时间轴上的这两个区间,所有LXRT任务并非处于真正的硬实时状态,期间任何操作都有可能因其不稳定性导致1020微秒的实时误差(具体数值未做严密测量)。这一点在RTAI自身文档中也有阐述,但因为不引人注意,使得基于RTAI/LXRT的实时控制开发人员非常容易忽略。对这一问题的

30、最简单处理办法就是在调用rt_make_hard_real_time()后随即插入短暂的等待,再进入实时处理阶段。实践中笔者在等待500微秒后得到理想的实时表现。4. stop_rt_timer是全局变量,如果在进程中某个线程结束时候使用,则会结束全部线程的定时器。解决这种情况可以,一,全部用周期,这样既不用去start也不用去stop;二,每个单独启动oneshot定时,然后在最后再结束。5. LXRT Tips And Tricks六. 管道通讯包含头文件#include rtai_sched.h1. 发送函数int rt_mbx_send (MBX* mbx, void* msg, in

31、t msg_size);/无条件发送消息int rt_mbx_send_wp (MBX* mbx, void* msg, int msg_size); /在不阻塞当期调用的任务的情况下,尽可能多的发送数据。消息长度是msg_ rt_mbx_send_if (MBX* mbx, void* msg, int msg_size);/发送一个消息, 要求在不阻塞当前调用任务的情况下,整个消息可以完整传递。int rt_mbx_send_until (MBX* mbx, void* msg, int msg_size, RTIMEtime);int rt_mbx_send_timed

32、(MBX* mbx, void* msg, int msg_size, RTIMEdelay);/rt_mbx_send_until和rt_mbx_send_timed发送消息msg_size大小的msg到邮箱mbx。调用者将被阻塞,直到所有字节的入消息队列、超时过期或发生错误。函数返回成功,未寄出的字节的数量被返回;失败,返回负值,负值定义如下:EINVAL mbx指向无效的mailbox(mbx points to not a valid mailbox).2. 接收函数int rt_mbx_receive (MBX* mbx, void* msg, int msg_size);/无条件接

33、受消息int rt_mbx_receive_wp (MBX* mbx, void* msg, int msg_size);/在不阻塞当期调用的任务的情况下,尽可能多的接收数据。int rt_mbx_receive_if (MBX* mbx, void* msg, int msg_size);/整个msg_size大小的消息能立刻获取到时,接收消息。int rt_mbx_receive_until (MBX* mbx, void* msg, int msg_size, RTIMEtime);int rt_mbx_receive_timed (MBX* mbx, void* msg, int ms

34、g_size, RTIMEdelay);/调用者将被阻塞,直到所有字节的入消息队列、超时过期或发生错误。time是绝对值,Delay是相对于当前时间的相对值.函数返回成功,返回收到的字节数量。失败,返回一个负值,定义如下:EINVAL mbx指向无效的mailbox(mbx points to not a valid mailbox).3. 示例代码/* messqueue.c*/* - headers - */#include #include #include #include #include #include #include #include #include #include /*

35、 error codes */#include #include #include #include #include /* - globals - */* turn on(1) or off(0) debugging */const int DEBUG=1;/ fix include warning/#include /#include int pthread_cancel_rt(pthread_t thread);/ linux threads idsstatic int thread1;static int thread2;/ realtime task structuresstatic

36、 RT_TASK *t1;static RT_TASK *t2;/ message queuestatic MBX *mesgQueueId;#define MAX_MESSAGES 100#define MAX_MESSAGE_LENGTH 50/* - functions - */void taskOne(void *arg) int retval; char message = Received message from taskOne; /* make this thread LXRT soft realtime */t1 = rt_task_init_schmod(nam2num(T

37、ASK1), 0, 0, 0, SCHED_FIFO, 0xF);mlockall(MCL_CURRENT | MCL_FUTURE); / makes task hard real time (only when not developing/debugging) if ( !DEBUG ) rt_make_hard_real_time(); rt_printk(Started taskOnen); /* send message */retval = rt_mbx_send(mesgQueueId, message, sizeof(message); if (0 != retval) if

38、 (-EINVAL = retval) rt_printk(mailbox is invalidn); else /* unknown error */ rt_printk(Unknown mailbox errorn); void taskTwo(void *arg) int retval; char msgBufMAX_MESSAGE_LENGTH; /* make this thread LXRT soft realtime */t2 = rt_task_init_schmod(nam2num(TASK2), 0, 0, 0, SCHED_FIFO, 0xF);mlockall(MCL_

39、CURRENT | MCL_FUTURE); / makes task hard real time (only when not developing/debugging) if ( !DEBUG ) rt_make_hard_real_time(); rt_printk(Started taskTwon); /* receive message */ retval = rt_mbx_receive_wp(mesgQueueId, msgBuf, 50); if (-EINVAL = retval) rt_printk(mailbox is invalidn); else rt_printk

40、(message length=50-%dn,retval);rt_printk(message : %sn,msgBuf); void cleanup(void) /* delete message queue */ rt_mbx_delete(mesgQueueId); / task end themselves - not necesssary to delete them return;/* - main - */int main(void) printf(Start of mainn); /* make this thread LXRT soft realtime */ rt_tas

41、k_init_schmod(nam2num(TASK0), 0, 0, 0, SCHED_FIFO, 0xF); mlockall(MCL_CURRENT | MCL_FUTURE); / set realtime timer to run in oneshot mode rt_set_oneshot_mode(); / start realtime timer and scheduler start_rt_timer(1); /* create message queue */ mesgQueueId = rt_typed_mbx_init (nam2num(MSGQUEUE), MAX_M

42、ESSAGES, FIFO_Q); if (mesgQueueId = 0) printf(Error creating message queuen); return 1; / create the linux threads thread1 = rt_thread_create(taskOne, NULL, 10000); thread2 = rt_thread_create(taskTwo, NULL, 10000); / wait for end of program printf(TYPE TO TERMINATEn); getchar(); / cleanup cleanup();

43、 printf(Finishedn); return 0;七. 共享内存通讯一. 创建函数void *rtai_malloc_adr (void *adr, unsigned long name, int size);void *rtai_malloc (unsigned long name, int size);void *rtai_kmalloc (unsigned long name, int size);/rtai_malloc_adr和rtai_malloc用于在用户空间分配而rtai_kmalloc用于在内核空间。分配参数adr用户期望的地址,被分配的内存应该映射到用户空间。nam

44、e无符号长标识符size需要的共享内存数量由于name可以是一个复杂的标识符,系统提供了将6字符标识符转换为无符长整型的服务,反之亦然。由函数nam2num 和 num2nam实现。unsigned long nam2num (const char *name);void num2nam(unsigned long id, const char* name);必须说,第一个分配做一个真正的分配, 从Linux进程调用的任何具有相同名称的后续分配,只是将区域映射到用户空间,或者返回相关指针到已经在内核空间中分配的空间。这个函数返回一个指针指向被分配的内存,适当地映射到使用的内存空间。函数返回成功

45、,返回一个有效地址失败,返回0.注意:如果同一个进程在同一个进程中调用了rtai_malloc_adr 和 rtai_malloc两次,将会在第二次调用时返回0.二. Free函数void rtai_free (unsigned long name, void *adr);void rtai_kfree(void *adr);rtai_free用于释放用户空间中一个以前分配的共享内存,rtai_kfree是用来在内核空间中做同样的操作。参数Name 当内存被分配时候使用的无符号长整型标识符Adr对应的地址注意类似分配函数的操作,释放调用只对取消映射共享内存有影响,这些共享内存到最后被释放,这时

46、才是真正的释放分配的内存。4. 示例代码(/)/* shm_task.c Set up a periodic task that increments a heartbeat array in shared memory.*/#define MODULE#define _KERNEL_#include #include #include /* ENOMEM */#include /* sizeof() */#include rtai.h#include rtai_sched.h#include rtai_shm.h#include com

47、mon.h /* SHM_KEY, SHM_HOWMANY */MODULE_LICENSE(GPL);RT_TASK shm_task;static RTIME shm_period_ns = 100000;static int * shm_array = 0;static void shm_function(int arg) int heartbeat = 0; int t; while (1) heartbeat+; /* make sure the memory has been allocated before we write to it */ if (0 != shm_array

48、) /* now write to it */ for (t = 0; t SHM_HOWMANY; t+) shm_arrayt = heartbeat; rt_task_wait_period(); return;int init_module(void) int retval; RTIME shm_period_count; shm_array = rtai_kmalloc(SHM_KEY, SHM_HOWMANY * sizeof(int); if (0 = shm_array) return -ENOMEM; rt_set_periodic_mode(); shm_period_co

49、unt = nano2count(shm_period_ns); start_rt_timer(shm_period_count); retval = rt_task_init(&shm_task, shm_function, 0, 1024, RT_LOWEST_PRIORITY, 0, 0); if (0 != retval) return retval; retval = rt_task_make_periodic(&shm_task, rt_get_time() + shm_period_count, shm_period_count); if (0 != retval) return

50、 retval; return 0;void cleanup_module(void) rt_task_delete(&shm_task); rtai_kfree(SHM_KEY); return;/*-*/#include /* printf() */#include /* sizeof() */#include /* signal(), SIGINT */#include /* PROT_READ, needed for rtai_shm.h */#include /* off_t, needed for rtai_shm.h */#include /* O_RDWR, needed for rtai_shm.h */#include /* rtai_malloc,free() */#include common.h /* SHM_KEY, SHM_HOWMANY */* This signal handler just sets the done flag, which we will loop on when printing the shared memory. This lets us quit nicely. */static int done = 0;static void qu

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论