LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - General (https://www.linuxquestions.org/questions/linux-general-1/)
-   -   Proc filing system repeatly accessed (https://www.linuxquestions.org/questions/linux-general-1/proc-filing-system-repeatly-accessed-4175554984/)

Regenerator 10-01-2015 06:23 AM

Proc filing system repeatly accessed
 
Hi folks,
I'm working on an iMX6 board with a Yocto build of Linux 3.10.17. I have a altered a bit of startup code that sets up a hardware timer. This is working fine. I needed to add an interface to this code so I added a proc filing system interface mainly along the lines of
http://tuxthink.blogspot.co.uk/2013/...-entry-in.html
This works and I can alter my timer as expected. However when ever I read or write to the /proc/file it gets repeatedly activated. I have debug print outs in both functions and they just spew out for ever.
A difference in my code to the example is that I don't have
MODULE_LICENSE("GPL"); module_init(proc_init); module_exit(proc_cleanup);
as I don't think it is a module on it's own (the code calling it may be) and the proc_init() is definately being called and the "module" is never unloaded.

Anyone know the ins and outs of the proc filing system and what happens when you access it? I realise my application is a little unusual (and I'm a novice at Linux, but not embedded stuff) so bear with me. It works but flies off the handle once activated, so close!

I've added the module_init(proc_init); module_exit(proc_cleanup); and I see no difference in this behaviour.

rtmistler 10-01-2015 06:58 AM

That link has nothing to do with creating a /proc file system. /proc is part of the kernel and is used extensively for just running processes. You can do a general web search and find lots of information about /proc. Basically everytime you run a process, which is a command, script, program, something which "runs" on your system. And yes typing "ls" creates a process, then the /proc file system is affected. The file system is real, but temporary, and thus volatile. Meaning it will not be retained and typically is not on a physical disk, but instead in RAM. If you explore the /proc file system you will discover that it contains all the relevant information about each process on your system.

What exactly is your problem? Or are you just asking for further information about /proc?

Regenerator 10-01-2015 07:09 AM

Sorry the link was not specific to the point in the web page - this is:
http://tuxthink.blogspot.co.uk/2013/...-entry-in.html

My problem is that the proc file system entry does what I want it to (updating my kernel programmed timer), but it then goes into a loop and blocks the terminal.
i.e. if I cat /proc/timer i get the values I expect printed out repeatedly
if I echo "1234" > /proc/timer the timer modifies to the setting but the write_proc() function is repeated called blocking the terminal.

I've since found if I get the read and write functions to return -1, the console report an error but the functions do their operation and there are no repeats for either the read or write. It means I can work with it now, but does it provide a clue to what's going on?

rtmistler 10-01-2015 12:24 PM

Not sure what the exact problem is, you may wish to post your code for others to look at, where someone can offer a suggestion as to where to debug, or if they notice an obvious bug by looking at it.

Regenerator 10-02-2015 09:36 AM

OK. Here goes. The relevant bits. Chopped for brevity.
[code]

static long lepit_reload_high_us = 250;
static long lcam_fs_freq_hz = 30;
static int epit_read_proc( struct file *filep, const char *buffer, size_t count, loff_t *offp );
static int epit_write_proc( struct file *filep, const char *buffer, size_t count, loff_t *offp );

struct file_operations proc_fops =
{
read: epit_read_proc,
write: epit_write_proc
};

static int epit_read_proc( struct file *filep, const char *buffer, size_t count, loff_t *offp )
{
char acstrbuffer[128];
int len;
sprintf(acstrbuffer, "Epit Camera Timing: Framerate ld Hz, Exposure ld us\n", lcam_fs_freq_hz , lepit_reload_high_us );
len = strlen(acstrbuffer);
if (count < len)
{
len = count;
}
copy_to_user(buffer, acstrbuffer, len);
return -1;
}

static int epit_write_proc( struct file *filep, const char *buffer, size_t count, loff_t *offp )
{
char acstrbuffer[128];
char *pacBuff;
int iRetVal = 0;
int iNumLen = 0;

copy_from_user( acstrbuffer, buffer, count );
// pr_err("epit_write_proc: %s\n", acstrbuffer);
pacBuff = acstrbuffer;
/* parse the frame-rate */
lcam_fs_freq_hz = str2int( pacBuff, &iNumLen);
pacBuff += iNumLen;

// pr_err("epit_write_proc: Frame Rate = %d Exposure (us) = %d\n", lcam_fs_freq_hz, lepit_reload_high_us );
return -1;
}

void epit_proc_cleanup(void)
{
/* clean up */
remove_proc_entry("epit_cam_timing", NULL);
}

void epit_proc_init(void)
{
/* use a proc file to pass in Exposure value and frame-rate */
if ( proc_create("epit_cam_timing", 0, NULL, &proc_fops) == NULL)
{
pr_err("Unable to register \"epit_cam_timing\" proc file\n");
}
}

void __init epit_timer_init(void __iomem *base, int irq)
{
struct clk *timer_clk;
int ret;

timer_clk = clk_get_sys("imx-epit.1", "ipg");
if (IS_ERR(timer_clk)) {
pr_err("i.MX epit: unable to get clk\n");
return;
}

clk_prepare_enable(timer_clk);
timer_base = base;

// pr_err("epit_timer_init: Frame Rate = %ld Exposure (us) = %ld", lcam_fs_freq_hz, lepit_reload_high_us );

/* Initialise to a known state (all timers off, and timing reset) */
__raw_writel(0x0, timer_base + EPITCR);

/* Make irqs happen */
ret = setup_irq(irq, &epit_timer_irq);
}

static struct irqaction epit_timer_irq = {
.name = "i.MX EPIT Timer Tick",
.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
.handler = epit_timer_interrupt,
};

static struct clock_event_device clockevent_epit = {
.name = "epit",
.features = CLOCK_EVT_FEAT_ONESHOT,
.set_mode = epit_set_mode,
.set_next_event = epit_set_next_event,
.rating = 200,
};

static int __init epit_clockevent_init(struct clk *timer_clk)
{
clockevents_config_and_register(&clockevent_epit,
clk_get_rate(timer_clk),
0x800, 0xfffffffe);

return 0;
}

/*
* IRQ handler for the timer
*/
static irqreturn_t epit_timer_interrupt(int irq, void *dev_id)
{
// struct clock_event_device *evt = &clockevent_epit;
uint32_t epit_current_reload_value;
struct timespec temptime;
static bool boHighToLow = false;
long lTimeOffset, lOffsetCount, labsTimeOffset;
// static int iCount = 0;

__raw_writel( epit_current_reload_value, timer_base + EPITLR);
// iCount++;

epit_irq_acknowledge();

//evt->event_handler(evt);

return IRQ_HANDLED;
}

module_init(epit_proc_init);
module_exit(epit_proc_cleanup);

[\code]

Regenerator 10-06-2015 03:49 AM

Anyone familiar with the proc mechanism to understand why it should be repeatedly called/accessed?

sundialsvcs 10-06-2015 06:42 AM

The "/proc file system," like "/sys," is actually an API provided by the kernel.

... And, a damned clever one, because anyone and anything can very easily use it: just access "a file" or "a directory.'" You get the information you need, in easily-consumable text form. And, if authorized, you can modify settings the same way.

None of these files or directories physically exist, yet you'd never know it.

This, to me, is one of the most brilliant parts of Linux's design. In most operating systems I have used, "getting internal information about the system" was a very difficult thing to do, often requiring privileged "voodoo programming" that was highly dependent on the exact format of internal binary data structures, and which could blow the system down if anything was done wrong. (The other most-brilliant part, to me, is PAM.)

rtmistler 10-06-2015 07:53 AM

Quote:

Originally Posted by Regenerator (Post 5430604)
Anyone familiar with the proc mechanism to understand why it should be repeatedly called/accessed?

/proc was described before, and once again now by sundialsvcs. I think the real question here is what's wrong with your particular implementation. Note that it would be helpful if you edited your posting of code and use [/code] at the end so that it will encapsulate properly. You used the BACKSLASH as opposed to the FORWARD SLASH prior to the word "code" in your closing statement.

There's nothing wrong with /proc being accessed repeatedly, it is ephemeral, meaning volatile and can be access as much as needed.

Sounds like your particular issue is that your wrote a module and there's something in there taking too much time or resources and looping excessively. Or, it may be correct code and the work that it is doing is extremely taxing to your system. But as programmers, we typically encounter a situation where what we've written is not as efficient as it can be and find that this is the problem.

I see no obvious loops nor excessive debug statements. I'd ensure that you have sufficient space for that sprintf() statement length. The characters take up about half of it, but you are printing using ld ... but wait a minute, you have a minor bug. PERCENT ld. And maybe it is there, I've come to find that some posts, replies the percent character gets lost unless you delimit it in some manner. I shall not try to reproduce, I've grown to use the word as I did a few lines ago. Either case, the long print of a decimal can be a lot of characters, you're printing two of them and the buffer is only 128 bytes in length. I'm assuming *buffer has sufficient length as well? Although there is a length test.

Other than that, printk() I believe is available to you in a module?

Is there an actual problem, or just you not understanding why it chooses to access the /proc file system so much? And what do you consider to be a lot? I think also if you're entering and exiting this module repeatedly, then it is going to access /proc a lot just to create and remove the /proc entry, as directed. Then of course each time it reads and writes, it will access /proc, because that's what it's designed to do.


All times are GMT -5. The time now is 01:03 AM.